Conceptual MCP server: four business tools
Words made simple
A few useful meanings before you read the explanation.
- MCP
- A shared protocol for connecting AI applications to tools and resources. It does not replace permission checks or application security.
- API
- A way for one piece of software to ask another for data or an action. A claims API might return the current status of a claim.
- JSON
- A common text format for exchanging data using named fields, lists, numbers and values. Example: {"status": "pending"}.
More words from this lesson
- Schema
- A description of the fields and value types that data should contain. It helps check that an answer has the expected shape.
- Agent
- An application that uses a model to choose its next action within defined limits. It can use tools and continue through several steps.
- Persistence
- Saving information so it remains available after a request ends or a process restarts.
- Durable
- Able to retain progress and recover across interruptions. Durable workflows require appropriate storage and retry behavior.
- Idempotency
- Making a repeated request have the same intended business effect as one request. It helps avoid duplicate submissions or payments.
- This example defines server-side contracts and dispatch logic, not a particular MCP SDK's registration syntax.
- Attach this registry to the selected SDK's authenticated request handlers, implement capability discovery, and encode its documented result envelopes.
- This separates the durable engineering idea from rapidly changing transport APIs.
import { z } from "zod";
type Principal = { userId: string; tenantId: string; scopes: readonly string[] };
type Services = {
customerForCaller(p: Principal, customerId: string): Promise<unknown>;
orderForCaller(p: Principal, orderId: string): Promise<unknown>;
createTicket(p: Principal, subject: string, body: string, key: string): Promise<unknown>;
searchKnowledge(p: Principal, query: string): Promise<unknown>;
};
const Id = z.string().regex(/^[A-Za-z0-9_-]{1,80}$/);
const registry = {
customer_lookup: { schema: z.object({ customerId: Id }).strict(), scope: "customer:read" },
order_lookup: { schema: z.object({ orderId: Id }).strict(), scope: "order:read" },
ticket_create: {
schema: z.object({
subject: z.string().min(1).max(200),
body: z.string().min(1).max(5000),
}).strict(),
scope: "ticket:create",
},
knowledge_search: {
schema: z.object({ query: z.string().min(1).max(1000) }).strict(),
scope: "knowledge:read",
},
} as const;
async function executeTool(
name: string, raw: unknown, principal: Principal, services: Services,
operationKey?: string,
): Promise<unknown> {
// principal comes from verified middleware, never model-supplied JSON.
if (!Object.prototype.hasOwnProperty.call(registry, name)) {
throw new Error("Unknown tool");
}
const toolName = name as keyof typeof registry;
if (!principal.scopes.includes(registry[toolName].scope)) {
throw new Error("Tool scope denied");
}
switch (toolName) {
case "customer_lookup": {
const a = registry.customer_lookup.schema.parse(raw);
return services.customerForCaller(principal, a.customerId);
}
case "order_lookup": {
const a = registry.order_lookup.schema.parse(raw);
return services.orderForCaller(principal, a.orderId);
}
case "ticket_create": {
const a = registry.ticket_create.schema.parse(raw);
// Reuse the host's persisted key for this logical write across retries.
// The model cannot mint a new key to turn a retry into another ticket.
const key = Id.parse(operationKey);
return services.createTicket(principal, a.subject, a.body, key);
}
case "knowledge_search": {
const a = registry.knowledge_search.schema.parse(raw);
return services.searchKnowledge(principal, a.query);
}
}
}- The
Servicesdependency deliberately owns object authorization and business rules. - Scope checks alone are insufficient.
- The trusted host persists
operationKeyfor one logical write and reuses it across retries; it is not a model-generated argument. createTicketmust enforce idempotency atomically and reject a changed payload under the same key, and the host/server must impose any required approval policy.- Read results should omit unnecessary PII.
- Add deadlines, rate limits, output schemas, bounded sizes, audit events, and safe error envelopes in the transport layer.
How the agent consumes this server: the host establishes trusted identity, discovers allowed contracts, translates them to the model's tool format, receives a proposed call, applies its approval policy, sends the MCP request, validates the returned result, and supplies the observation to the model. In the insurance domain, order_lookup might become policy-order lookup, ticket_create creates a support case, and knowledge_search retrieves policy instructions. Claim submission would be a separate, more restrictive capability.
Can you explain it without the notes?
Conceptual MCP server: four business tools
Use your own words. Explain an example and one limitation before checking the explanation.
Check your explanation
This example defines server-side contracts and dispatch logic, not a particular MCP SDK's registration syntax. Attach this registry to the selected SDK's authenticated request handlers, implement capability discovery, and encode its documented result…
Turn this concept into a clear answer.
Practice this conceptKeep connecting the ideas.
Next lesson: Context, short-term memory, and conversation memoryAdapted from 13_AI.MD · “Conceptual MCP server: four business tools”. Examples are study fragments; framework behavior can depend on your version.