Expose Tools over MCP

medium10 minmcp-server.ts

Your inventory tools should be usable from any MCP client — Claude Desktop, Cursor or another agent.

What it shows

  • Register Cogitator tools and a resource template on MCPServer
  • Serve over HTTP; a thrown error reaches the client as MCPToolError

The code

mcp-server.ts
import { Agent, Cogitator, tool } from '@cogitator-ai/core';
import { MCPClient, MCPServer, MCPToolError } from '@cogitator-ai/mcp';
import { z } from 'zod';

const apiKey = process.env.GOOGLE_API_KEY;
if (!apiKey) throw new Error('Set GOOGLE_API_KEY');

const stock: Record<string, number> = { 'SKU-42': 137, 'SKU-7': 12 };

const lookupStock = tool({
  name: 'lookup_stock',
  description: 'Look up how many units of a product SKU are in stock.',
  parameters: z.object({ sku: z.string().describe('Product SKU, e.g. "SKU-42"') }),
  execute: async ({ sku }) => ({ sku, units: stock[sku] ?? 0 }),
});

const reserveUnits = tool({
  name: 'reserve_units',
  description: 'Reserve units of a product. Fails if not enough stock is available.',
  parameters: z.object({ sku: z.string(), units: z.number().int().positive() }),
  execute: async ({ sku, units }) => {
    const available = stock[sku] ?? 0;
    if (units > available) throw new Error(`Only ${available} units of ${sku} available`);
    stock[sku] = available - units;
    return { sku, reserved: units, remaining: stock[sku] };
  },
});

const server = new MCPServer({
  name: 'inventory',
  version: '1.0.0',
  transport: 'http',
  host: '127.0.0.1',
  port: 0,
});
server.registerTools([lookupStock, reserveUnits]);
server.registerResource({
  uri: 'inventory://sku/{sku}',
  name: 'sku',
  mimeType: 'application/json',
  read: async ({ sku }) => ({
    uri: `inventory://sku/${sku}`,
    text: JSON.stringify({ sku, units: stock[sku] ?? 0 }),
  }),
});
await server.start();

const client = await MCPClient.connect({
  transport: 'http',
  url: `http://127.0.0.1:${server.getPort()}/mcp`,
});

try {
  console.log(await client.callTool('lookup_stock', { sku: 'SKU-42' }));
  console.log((await client.readResource('inventory://sku/SKU-7')).text);

  try {
    await client.callTool('reserve_units', { sku: 'SKU-7', units: 999 });
  } catch (error) {
    if (!(error instanceof MCPToolError)) throw error;
    console.log('Refused:', error.message);
  }

  const cog = new Cogitator({ llm: { providers: { google: { apiKey } } } });
  const agent = new Agent({
    name: 'inventory-assistant',
    model: 'google/gemini-3.5-flash-lite',
    instructions: 'You manage inventory. Use the tools to check stock and reserve units. Be concise.',
    tools: await client.getTools(),
    temperature: 0.2,
  });
  const result = await cog.run(agent, { input: 'Reserve 40 units of SKU-42 and tell me what remains.' });
  console.log(result.output);
  await cog.close();
} finally {
  await client.close();
  await server.stop();
}

Run it

install · bash
pnpm add @cogitator-ai/core @cogitator-ai/mcp zod
EnvironmentGOOGLE_API_KEY
run · bash
GOOGLE_API_KEY=your-key npx tsx mcp-server.ts

Or run the full example from a clone of the repository (keys in .env):

repository · bash
npx tsx examples/mcp/02-mcp-server.ts

Learn more