112 lines · 4.2 KB
import { meterMethod } from "./audit";
import { LEGACY_VERSIONS, META, RPC, RpcError, SERVER_INFO, SERVER_INSTRUCTIONS, SUPPORTED_VERSIONS } from "./protocol";
import type { JsonObject, McpCaller } from "./protocol";
import { getPrompt, PROMPTS } from "./prompts";
import { listResources, readResource, RESOURCE_TEMPLATES, subscribeResource } from "./resources";
import { callTool, listTools } from "./tools";
import type { ToolContext } from "./tools/base";

const LIST_TTL_MS = 60 * 60 * 1000;
const READ_TTL_MS = 30 * 1000;

function capabilities(era: "modern" | "legacy"): JsonObject {
  return {
    tools: { listChanged: false },
    resources: { subscribe: true, listChanged: false },
    prompts: { listChanged: false },
    ...(era === "legacy" ? { logging: {} } : {}),
  };
}

export function negotiateLegacyVersion(requested: unknown): string {
  return typeof requested === "string" && (LEGACY_VERSIONS as readonly string[]).includes(requested)
    ? requested
    : LEGACY_VERSIONS[0];
}

export function initializeResult(protocolVersion: string): JsonObject {
  return {
    protocolVersion,
    capabilities: capabilities("legacy"),
    serverInfo: SERVER_INFO,
    instructions: SERVER_INSTRUCTIONS,
  };
}

function cacheable(caller: McpCaller, ttlMs: number, scope: "public" | "private"): JsonObject {
  return caller.era === "modern" ? { ttlMs, cacheScope: scope } : {};
}

function stringParam(params: JsonObject, key: string): string {