MCP's integration boundary
The Model Context Protocol architecture separates three roles. The host is the AI application coordinating model interaction, context and consent. A client inside it maintains a protocol session with one server, which exposes capabilities. These are logical roles; they need not occupy separate machines. The teaching baseline here is revision 2025-06-18, not a claim about the latest revision.
An agent runtime is application machinery that coordinates model requests and execution. MCP can supply capabilities through an adapter while the runtime retains the decision loop and context management. Scheduling, persistence and recovery belong to Harness Engineering. Moving an issue-tracker adapter behind an MCP server changes its callers, not the need to implement it.
The standardized boundary
ExampleClients standardize access; backend adapters remain.
Read the diagram as text
- Host application. Context, model interaction and policy.
- Model.
- Issue client.
- Document client.
- Issue MCP server.
- Document MCP server.
- Issue backend.
- Document backend.
- Host application → Model: Data: model input.
- Host application → Issue client: Contains client.
- Host application → Document client: Contains client.
- Issue client → Issue MCP server: Data: MCP requests.
- Document client → Document MCP server: Data: MCP requests.
- Issue MCP server → Issue backend: Data: backend API.
- Document MCP server → Document backend: Data: backend API.
| Integration | Reusable boundary | Work retained |
|---|---|---|
| Direct adapter | An application calls its own integration functions. | Backend semantics, permissions, failures and maintenance. |
| MCP server | Several compatible applications discover and invoke the same interfaces. | Backend adapter plus server deployment, client compatibility and operating controls. |
Tools as callable operations
A tool is a named operation with an argument contract and returned content. tools/list discovers definitions; tools/call supplies a name and arguments. inputSchema describes admissible arguments. An optional outputSchema constrains structured results, and clients should validate them. Tool contracts explain schema shape versus operational meaning.
In an example wrapper, update_issue accepts repository, issue number and labels. Its result can include server-produced JSON in structuredContent, accompanied by serialized JSON in a text content block. This is returned application data, distinct from constrained model generation. Descriptions guide selection; annotations such as readOnlyHint do not enforce permission.
From declaration to execution
Model output becomes an operation only after dispatch.
Read the diagram as text
- Discovered definition.
- Host adaptation.
- Model proposal.
- Dispatch gate.
- Rejected; no dispatch.
- Server execution.
- Returned result.
- Host result validation.
- Discovered definition → Host adaptation: Data: schema.
- Host adaptation → Model proposal: Data: model declaration.
- Model proposal → Dispatch gate: Data: proposed arguments.
- Dispatch gate → Rejected; no dispatch: Control: denied.
- Dispatch gate → Server execution: Control: authorized dispatch.
- Server execution → Returned result: Data: result.
- Returned result → Host result validation: Data: validation input.
The host adapts discovered declarations to its model provider's tool interface. The model proposes an operation; application code decides whether to dispatch it through the MCP client. The returned observation can then inform another model request. An SDK may automate this loop, but that automation is an SDK behavior rather than orchestration supplied by MCP.
Resources as addressable information
An MCP resource is information identified by a URI, an address that need not be a web URL or physical file. resources/list discovers descriptions; resources/templates/list exposes parameterized addresses; resources/read retrieves text or base64 binary. A MIME type labels the content format.
An issue wrapper might resolve issue://{repository}/{number} into issue://demo/42. Reading supplies a snapshot; the host separately decides whether to include it. Application-controlled describes that decision point, even if a model helps choose the resource. Context selection and refresh govern its usefulness in later requests.
One resource, successive snapshots
ExampleNotification, retrieval and inclusion are separate.
Host includes A.
Read the diagram as text
- Issue resource.
- Snapshot A.
- A included.
- Refresh required.
- Snapshot B.
- B included.
- Issue resource → Snapshot A: Read.
- Snapshot A → A included: Host inclusion.
- Issue resource → Refresh required: Update notice.
- Issue resource → Snapshot B: Fresh read.
- Snapshot B → B included: Host replacement.
- Included. Host includes A. Active: Issue resource, Snapshot A, A included. New: Issue resource, Snapshot A, A included.
- Changed. Notice identifies changed content. Active: Issue resource, Snapshot A, A included, Refresh required. New: Refresh required.
- Retrieved. Read obtains B; A remains included. Active: Issue resource, Snapshot A, A included, Refresh required, Snapshot B. New: Snapshot B.
- Replaced. Host includes B; A remains historical. Active: Issue resource, Snapshot A, Snapshot B, B included. New: B included.
Resources can teach a workflow as well as supply records. Backlog.md exposes an overview and guides for task creation, execution and completion alongside callable task operations. The guides explain procedure; their presence does not guarantee that a client reads them or an agent follows them.
Prompts as reusable interaction templates
An MCP prompt is a server template that accepts arguments and returns messages. prompts/list discovers templates; prompts/get resolves one. Retrieving messages neither invokes a model nor executes their suggested operations. User-controlled means intended for explicit selection, not that the user authored or trusts every returned instruction.
An issue-review template can accept issue text and return a user message requesting a summary and proposed labels. This adapts the documented code-review pattern. The host chooses whether and how to incorporate the message through context assembly. A slash command is one possible interface, not a protocol requirement.
| Interface | Exchange | Material and customary control |
|---|---|---|
| Tool | tools/list → tools/call | Operation result; commonly model-selected, application-dispatched. |
| Resource | resources/list → resources/read | Addressed content; host selects context. |
| Prompt | prompts/list → prompts/get | Messages; commonly user-selected, host-incorporated. |
Message exchange and session readiness
JSON-RPC 2.0 is MCP's message envelope. A request names a method and carries a non-null string or integer ID. Its response repeats that ID and contains either result or error. A notification has no ID and receives no response. In this revision, each sender must not reuse its request IDs within the session.
Capability negotiation exchanges supported protocol features during initialization. Both peers declare capabilities. The client proposes a version; the server echoes it if supported or returns another supported version. Before readiness, traffic is restricted to the specified ping and logging exceptions. Normal operations must respect the agreed version and features.
Readiness requires agreement
A connection alone does not enable normal operations.
Read the diagram as text
- Transport open.
- Negotiation pending.
- Compatible; not ready.
- Ready for negotiated operations.
- Disconnected.
- Transport open → Negotiation pending: Client: initialize.
- Negotiation pending → Compatible; not ready: Returned version supported.
- Negotiation pending → Disconnected: Returned version unsupported.
- Compatible; not ready → Ready for negotiated operations: Client: notifications/initialized.
- Ready for negotiated operations → Disconnected: Transport termination.
For example, {"jsonrpc":"2.0","id":7,"method":"tools/list"} requests an inventory; {"jsonrpc":"2.0","id":7,"result":{"tools":[]}} answers that exchange. {"jsonrpc":"2.0","method":"notifications/initialized"} has no response to await. Correlation identifies an exchange, not a durable business operation.
Discovery and changing inventories
Server configuration locates a peer. Negotiation establishes feature families. Enumeration obtains concrete interfaces. These are separate stages: a tools capability does not identify which tools exist, and a discovered tool need not be presented to the model. Selective exposure is a host strategy for keeping a large catalog relevant, not a semantic-search guarantee supplied by pagination.
List responses may contain opaque nextCursor strings. Send that value as cursor for the next page; stop only when nextCursor is absent. Page length is not an end condition. Do not parse or modify cursors, assume fixed page sizes, or retain cursors across sessions. Pagination does not freeze a changing catalog.
| Signal | Meaning | Host consequence |
|---|---|---|
| notifications/tools/list_changed | Supported tool inventory changed. | Enumerate again; reconsider exposure. |
| notifications/prompts/list_changed | Supported prompt inventory changed. | Refresh available templates. |
| notifications/resources/list_changed | Resource inventory changed. | Refresh discovery. |
| notifications/resources/updated | Subscribed URI changed. | Read again; update context separately. |
An aggregated catalog should retain a routing identity such as (server, item name), rather than flattening overlapping names. Refresh also needs behavioral checks: a server can remain protocol-compatible while changing a tool or template enough to break a workflow. Supported syntax and stable meaning are different compatibility properties.
Transports and connection state
| Transport | Message delivery | Deployment obligation |
|---|---|---|
| stdio | Client launches a subprocess; newline-delimited JSON-RPC uses standard streams. | Keep stdout protocol-only; send logs to stderr. |
| Streamable HTTP | Each client message uses POST; responses can be JSON or Server-Sent Events. | Support both formats and validate Origin; authentication and binding local servers to localhost are recommended. |
Server-Sent Events, or SSE, carry server-to-client events; here those events contain protocol messages, not necessarily model tokens. An optional Mcp-Session-Id accompanies subsequent requests, alongside MCP-Protocol-Version. A session-related 404 requires fresh initialization. Disconnect is not cancellation in this revision. Optional event IDs and Last-Event-ID support replay on an interrupted stream, not business recovery.
Local deployment means approving executable code and the credentials available to its process. A local binary can use machine credentials and existing API libraries; it still needs appropriate permissions. A remote deployment moves process operation to a service operator. For a protected remote service, an authenticated network access boundary is required.
Session storage is an implementation concern. One demonstrated Lambda-hosted server stored session data in DynamoDB. That illustrates separating state from individual function executions; it establishes no general recovery guarantee. MCP defines no shutdown method in this revision: termination uses the transport.
Connection authorization and operation permission
Authentication establishes identity; authorization determines permitted access. A principal is the person or service whose authority is exercised. OAuth enables delegated access: a client obtains an access token from an authorization server and presents it to a resource server. Scope expresses requested or granted access; requested scope is not necessarily granted.
Under the pinned HTTP profile, the protected MCP service is an OAuth resource server, distinct from a resource returned by resources/read. Token audience identifies the intended recipient. Clients identify the MCP server through resource during authorization and token requests, and send bearer authorization on every HTTP request.
First access to a protected service
Token validation and operation permission are separate.
Read the diagram as text
- Client request without token.
- Discover authorization metadata.
- Authorization-server grant.
- MCP token validation.
- Operation authorization.
- Backend access.
- Rejected; no operation dispatch.
- Client request without token → Discover authorization metadata: 401: metadata pointer.
- Discover authorization metadata → Authorization-server grant: Discovered authorization service.
- Authorization-server grant → MCP token validation: Grant obtained: bearer request.
- Authorization-server grant → Rejected; no operation dispatch: Grant denied.
- MCP token validation → Rejected; no operation dispatch: Invalid token.
- MCP token validation → Operation authorization: Valid for this server.
- Operation authorization → Rejected; no operation dispatch: Insufficient permission.
- Operation authorization → Backend access: Allowed; separate upstream credential.
A bearer token is usable by its holder. Protected Resource Metadata tells the client where authorization services are located. PKCE, Proof Key for Code Exchange, ties code redemption to a client-held verifier: the authorization request carries a challenge, and the token request supplies the verifier. The authorization service checks their relationship before issuing the token.
| Boundary | Independent check |
|---|---|
| Host dispatch | Bind approval to actor, operation, target, material arguments and lifetime. Changed arguments need renewed approval; see approval binding. |
| MCP operation | Check the action against authority, not merely prior good behavior. Execution authority locates this gate. |
| Tenant data | A tenant is an isolated customer or organizational domain. Derive it from verified identity, then authorize the tenant-and-record combination; a model-supplied tenant ID is insufficient. |
| Backend API | Validate the incoming token for the MCP server. Never forward it upstream; use a separately authorized upstream token. |
Authority of server-provided content
Indirect prompt injection places instructions in retrieved material to redirect model behavior across an intended instruction boundary. An issue description delivered through an authenticated MCP resource can still contain such instructions. AI Security explains the underlying attack; MCP adds concrete entry points through descriptions, prompt messages, resources and tool results.
Discovery itself can expose an instruction channel. Historical tool-poisoning experiments placed malicious instructions in a server's tool description and redirected calls to another server's legitimate email tool. The malicious tool did not need to execute. These demonstrations establish a possible influence path, not that every host or model follows every injected instruction.
Provenance records origin and transformation history. Preserve the issue's source when incorporating or summarizing its text, as explained in content transformations. If that text asks the assistant to send private notes elsewhere, the resulting proposal still needs independent authorization. Retrieved content cannot grant privileges or authorize disclosure.
Limit the information returned to what the task needs. Removing unnecessary personal details, credentials and internal fields reduces material available for later disclosure. This complements enforcement; it does not make the remaining content immune to injection. Read-only access can still be excessive when it exposes unrelated conversations or records.
Optional requests for client assistance
| Negotiated client feature | Request and purpose | Boundary retained |
|---|---|---|
| Sampling | sampling/createMessage requests generation through the client. | Host controls model access, selection and permissions. Model preferences are advisory; users should be able to review prompts and responses or deny the request. |
| Roots | roots/list requests relevant workspace locations, using file URIs in this revision. | Clients apply permissions; servers validate paths. Declaring roots does not confine a process. Workspace isolation requires enforcement. |
| Elicitation | elicitation/create requests user information using a message and flat schema of primitive fields. | Sensitive information must not be requested. Accept with content, decline and cancel are distinct outcomes; supplying information is not blanket action approval. |
During a tool operation, a server can request sampling, receive client-mediated model output, and then complete its operation. This avoids separately configuring the server's direct model access; it does not make inference free. The client must implement the reverse request, and the server must integrate its response into the ongoing work.
Request association is version-sensitive. On a POST response stream, server requests should relate to the originating client request; an optional GET stream may carry unrelated server requests. The stronger universal association requirement belongs to a later design. Host policy still governs what assistance is permitted.
An interactive host can present an elicitation form, while a background application may have no human respondent. Having the model fill a confirmation field does not establish human approval. Required assistance therefore needs explicit unsupported and declined outcomes, with continuation policy owned by the runtime.
An issue review from discovery to confirmed state
The example integration uses a constructed MCP wrapper over GitHub issue operations. update_issue, the issue URI and the review template are example design choices. GitHub's backend contract remains decisive: supplying labels replaces the set, an empty array clears it, and label changes without push access can be silently dropped. Protocol success alone cannot resolve those semantics.
| Sender → receiver | Exchange or action | Fact established | Contract |
|---|---|---|---|
| Client → protected service | Connect and obtain authorization. | Credential available for this service. | HTTP authorization |
| Client ↔ server | Initialize; complete readiness. | Compatible session features. | MCP lifecycle |
| Client → server | Enumerate supported inventories. | Advertised interfaces, across pages. | MCP discovery |
| Client → server | Get review prompt; read issue 42. | Messages and issue snapshot received. | MCP interfaces |
| Host ↔ model | Assemble input; receive update proposal. | Candidate action, not execution. | Model adapter |
| Host ↔ user | Review target and exact change. | Bounded approval or rejection. | Application policy |
| Client → server → backend | tools/call invokes the wrapper; wrapper sends PATCH. | Attempt and returned issue representation. | MCP plus backend API |
| Host → backend, through adapter | Separate GET checks issue state. | Observed state, not actor attribution. | Backend verification |
A replacement write couples freshness to approval. If approved labels were ['bug','triaged'] but a fresh read now contains ['bug','customer'], preserving existing labels changes the proposed replacement to ['bug','customer','triaged']. The host must renew approval for those changed arguments. This reasoning assumes no further write during review and dispatch; concurrent updates need a backend-supported conflict policy.
Prompts, resources and tools cooperate here because the host chooses that workflow; an integration need not use all three. Context assembly determines the model input. Result interpretation determines justified completion claims. A narrated delivery incident illustrates the distinction: a tool reported success although the message did not appear at the user-facing surface.
Failures, cancellation and uncertain effects
| Observation | What it establishes | Next interpretation |
|---|---|---|
| JSON-RPC error | {"id":9,"error":{"code":-32602,"message":"Invalid params"},"jsonrpc":"2.0"} reports a protocol-level failure. | Inspect the failed request. |
| Tool error | {"isError":true,"content":[{"type":"text","text":"Update failed"}]} is a tool-result body. | Execution reported failure, not success. |
| HTTP authorization rejection | 401: missing/invalid authorization; 403: insufficient permission; 400: malformed authorization request. | Repair the corresponding authorization boundary. |
| Malformed result | Returned data fails its declared contract. | Reject downstream use; execution may already have occurred. |
| Transport loss or deadline | The caller lacks a usable final response. | Determine backend outcome before repeating effects. |
Progress is optional observation. A request supplies params._meta.progressToken, unique across active requests; notifications/progress returns increasing progress, optional total and optional message. Reports may be omitted and must stop after completion. Without a known total, a percentage is unjustified. Neither a progress report nor its token is a final result or durable job handle.
Committed state, uncertain caller
ExampleCancellation does not establish rollback.
Caller waits for the update.
Read the diagram as text
- Issue 42.
- Update request.
- Backend before update.
- Backend update committed.
- Caller awaiting response.
- Caller outcome unknown.
- Cancellation sent.
- Read-back observed.
- Issue 42 → Backend before update: Initial state.
- Update request → Backend update committed: Backend effect.
- Update request → Caller awaiting response: Caller waits.
- Update request → Caller outcome unknown: No final response.
- Caller outcome unknown → Cancellation sent: Stop request.
- Backend update committed → Read-back observed: Separate read.
- Dispatched. Caller waits for the update. Active: Issue 42, Update request, Backend before update, Caller awaiting response. New: Issue 42, Update request, Backend before update, Caller awaiting response.
- Committed. Backend commits; response is lost. Active: Issue 42, Update request, Backend update committed, Caller awaiting response. New: Backend update committed.
- Timed out. Cancellation cannot undo the commit. Active: Issue 42, Update request, Backend update committed, Caller outcome unknown, Cancellation sent. New: Caller outcome unknown, Cancellation sent.
- Reconciled. A fresh read observes resulting state. Active: Issue 42, Update request, Backend update committed, Cancellation sent, Read-back observed. New: Read-back observed.
Set request timeouts; on expiry, send cancellation and stop waiting. Progress may reset the timer, but retain an overall maximum. Excessively short timeouts can provoke retries and overload; excessively long waits retain resources. Remaining deadline budget must cover another attempt and its delay.
Either peer can send notifications/cancelled for its own previously issued, believed-active request; clients must not cancel initialize. Receivers should stop work and release resources, but may ignore unknown, completed or uncancellable requests. Senders should ignore late responses. Cancellation can arrive after completion and specifies no reversal of committed effects.
Idempotency makes retries of one logical operation avoid repeating its effect through a backend-enforced contract. A caller-provided operation key must be recorded atomically with the mutation and associated outcome; changed parameters under the same key require rejection. A JSON-RPC ID, log entry or replayed message does not implement that contract.
When a write's outcome is uncertain, retain its identity and seek authoritative status or reconcile state. Retry only under the backend's actual safety contract. Reversal requires a separate supported compensating action. Uncertain effects explains this boundary; durable execution belongs to Harness Engineering. Recovery controls must remain usable even when ordinary work is blocked.
Interoperability evidence and integration fit
A compatibility claim needs a named protocol revision, host, server, SDK versions and required feature set. The following matrix is a proposed test design, not executed results. Inspector documents fixtures for several interface cases, but neither those fixtures nor a successful connection certify the business workflow. Interface testing supplies the broader method.
| Case | Expected observation | Separate assertion | Evidence status |
|---|---|---|---|
| Incompatible returned version | Client disconnects. | No normal operations dispatched. | Proposed; unexecuted |
| Sampling unavailable | Host does not promise unsupported assistance. | Workflow reports its unmet requirement. | Proposed; unexecuted |
| Paginated or changing catalog | Pages consumed; changes trigger refresh. | Required operations remain selectable. | Proposed; unexecuted |
| Duplicate names; incompatible schema | Routing or validation behavior is visible. | Correct server chosen; unusable data rejected. | Documented fixture categories; unexecuted |
| Denied action | Enforcement rejects the operation. | Protected state remains unchanged. | Proposed; unexecuted |
| Subscribed content changes | Notification and subsequent host behavior recorded. | Fresh context reaches the next decision. | Documented fixture category; unexecuted |
| Response lost after a write | Caller records uncertainty. | Reconciliation precedes any unsafe retry. | Proposed; unexecuted |
Correlate client, server and backend activity while keeping request, attempt and business-operation identities distinct. Cross-service identity explains propagation. Shared trace identifiers connect instrumented work; they do not prove correct authorization or reveal an uninstrumented provider's internals. Compatibility evidence should end with the state or delivery boundary the user actually cares about.
| Requirement | Integration implication |
|---|---|
| One application owns its tools and loop | A direct adapter can be sufficient; MCP is not required for tool use. |
| Several independently maintained hosts need reusable capabilities | MCP can supply a shared interface, provided their required features interoperate. |
| An independent agent owns a delegated task | A2A provides task coordination and artifacts; it may use MCP internally. See Multi-Agent Systems. |
Open questions
Behavioral compatibility across server updates remains harder than message compatibility. A changed description or operation can alter an established workflow while remaining protocol-valid. Progress requires versioned workflow tests that detect semantic regressions, not only successful discovery.
Portable human assistance remains difficult across interactive and background hosts. A valid elicitation request may have no suitable respondent, and model-filled confirmation is not human consent. Progress means explicit, tested outcomes for unavailable, declined and accepted interactions without silently broadening authority.
Safe recovery across independently operated backends lacks a universal contract. After response loss, transport evidence cannot distinguish every committed effect from an unexecuted request. Progress requires documented operation-key retention, duplicate handling and authoritative reconciliation for each effectful integration.



































































































































































