@fusedashlabs/ui9000-workspace
Version:
UI9000 workspace MCP. One tool, show_workspace, draws a chart from your table. Set TYPESAFE_API_KEY to let Jev choose the chart.
79 lines (78 loc) • 3.5 kB
TypeScript
/**
* Thin MCP server. Registers exactly one tool: show_workspace.
*
* The handler is injected. This module does not import `handleShowWorkspace`,
* `src/engine`, or the catalog — it only moves JSON-RPC frames between a
* transport and the handler, so the tool contract can change without touching
* the server. The registered name is `SHOW_WORKSPACE_NAME` from the tool
* module so it cannot drift from the contract.
*
* In-process tests use this hand-rolled `handle()`. Live stdio
* (`startWorkspaceServer`) uses `createSdkWorkspaceServer` (MCP SDK 1.30 +
* ext-apps), the same wire Cursor issues `resources/read` against.
*/
import { SHOW_WORKSPACE_NAME } from '../tool/show-workspace.js';
import type { McpAppResource } from './mcp-app.js';
export { SHOW_WORKSPACE_NAME };
/** Injected implementation of show_workspace. Args arrive unparsed from the client. */
export type ShowWorkspaceHandler = (args: unknown) => unknown | Promise<unknown>;
/**
* Tool metadata. The real description and input schema live with the tool
* contract (S3-09) and are passed in; a stub may pass 'stub' or nothing.
*/
export type ShowWorkspaceToolInfo = {
description?: string;
inputSchema?: Record<string, unknown>;
/** When set, Cursor/Claude open `ui://` instead of the JSON data-link. */
appResource?: McpAppResource;
};
export type ToolDescriptor = {
name: string;
description?: string;
inputSchema: Record<string, unknown>;
_meta?: Record<string, unknown>;
};
export type JsonRpcId = string | number;
export type JsonRpcResponse = {
jsonrpc: '2.0';
id: JsonRpcId;
result?: unknown;
error?: {
code: number;
message: string;
data?: unknown;
};
};
export type McpServer = {
/** Always length 1. Exposed so callers can assert the surface without a round trip. */
readonly tools: readonly ToolDescriptor[];
/** Handles one decoded JSON-RPC message. Returns null for notifications. */
handle(message: unknown): Promise<JsonRpcResponse | null>;
};
export declare const PROTOCOL_VERSION = "2025-06-18";
/** Echo a supported client version. An absent or unknown one keeps the server default. */
export declare function negotiateProtocol(params: unknown): string;
export declare const SERVER_INFO: {
readonly name: "ui9000-core";
readonly version: "0.0.0";
};
/**
* Returned on initialize. Hosts such as Claude put this in context before they
* pick a tool. It does not remove the host's own chart tools.
*/
export declare const WORKSPACE_INSTRUCTIONS: string;
declare const PARSE_ERROR = -32700;
declare const INVALID_REQUEST = -32600;
declare const METHOD_NOT_FOUND = -32601;
declare const INVALID_PARAMS = -32602;
declare const INTERNAL_ERROR = -32603;
/**
* Builds the server. One tool, one handler, no registry: a second registerTool
* call is impossible by construction, so generate_* tools cannot appear.
*/
export declare function createServer(handler: ShowWorkspaceHandler, info?: ShowWorkspaceToolInfo): McpServer;
/** Same CallToolResult envelope the stdio SDK path returns. */
export declare function workspaceToolResult(result: unknown, appResource: McpAppResource | undefined): Record<string, unknown>;
export declare function okResponse(id: JsonRpcId, result: unknown): JsonRpcResponse;
export declare function errorResponse(id: JsonRpcId, code: number, message: string): JsonRpcResponse;
export { PARSE_ERROR, INVALID_REQUEST, METHOD_NOT_FOUND, INVALID_PARAMS, INTERNAL_ERROR };