# Expose one operation through API and MCP

Share the registered behavior while keeping authentication, transport formats and evidence explicit.

Source context: Source-guided
Source: https://github.com/lssm-tech/contractspec/blob/d58fa5b7de53a947811e5cc68346be028ce18528/packages/platform/delivery/contracts-runtime-server-mcp/src/mcp/registerTools.ts

## Start from one registry

Register the operation and bind its handler once. The REST createFetchHandler and MCP registerMcpTools implementations both call OperationSpecRegistry.executeResult. That shared invocation path is the useful connection between an API request and an agent tool call.

The adapters still serve different protocols. Share the operation's semantics and test transport-specific behavior instead of assuming their payloads will be identical.

## Configure context for each transport

REST accepts a context factory for each request and can adapt transport approval evidence. MCP uses a tool context factory and an approval adapter. Both copy the host context for a call so request-specific evidence does not have to mutate a shared object.

Resolve the caller on the server side. A tool argument that says it is an administrator is business input, not a trustworthy authenticated subject.

| Concern | REST | MCP |
| --- | --- | --- |
| Entry point | createFetchHandler | registerMcpTools |
| Business execution | Registry executeResult | Registry executeResult |
| Public shape | HTTP request and response | Tool schema and CallToolResult |
| Failure representation | Transport response from canonical result | isError plus canonical structuredContent |
| Approval evidence | Request-specific adapter/context | Tool-specific adapter/context |

## Compare a real denied call

Use a valid request to an operation that requires approval. Supply fixture identity but omit the receipt. Each actual adapter should reach the common approval check before the bound handler can run.

Record the wire output you observe. For MCP, the implementation returns isError and includes the canonical failure in structuredContent. For REST, inspect the response produced by its result mapper. Compare the meaningful error code and effect count, not incidental formatting.

## Add the human interface

A small form can call the same REST operation used by other clients. Its role is to help a person supply valid data and understand the result. It should not recreate the server's authorization logic as the only protection.

When you change a required field, update the form and inspect the MCP tool schema together. Validate both entry points: the MCP SDK may reject malformed input before it reaches the registry, while an HTTP request may fail inside the operation boundary.

## Related examples

- [Draft freely. Send with approval.](https://lssm.co/examples/draft-and-send-agent/): Follow one contract boundary through a workflow and an in-memory MCP transport.

