@hypothesi/tauri-mcp-server 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,132 +1,18 @@
1
1
  #!/usr/bin/env node
2
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
- import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
- import { zodToJsonSchema } from 'zod-to-json-schema';
6
2
  import { readFileSync } from 'fs';
7
3
  import { fileURLToPath } from 'url';
8
4
  import { dirname, join } from 'path';
9
- // Import the single source of truth for all tools and prompts
10
- import { TOOLS, TOOL_MAP } from './tools-registry.js';
11
- import { PROMPTS, PROMPT_MAP } from './prompts-registry.js';
12
- import { createMcpLogger } from './logger.js';
5
+ import { startStdioServer } from './server.js';
13
6
  /* eslint-disable no-process-exit */
14
7
  // Read version from package.json
15
8
  const currentDir = dirname(fileURLToPath(import.meta.url));
16
9
  const packageJson = JSON.parse(readFileSync(join(currentDir, '..', 'package.json'), 'utf-8'));
17
10
  const VERSION = packageJson.version;
18
- const serverLogger = createMcpLogger('SERVER');
19
- // Initialize server
20
- const server = new Server({
21
- name: 'mcp-server-tauri',
22
- version: VERSION,
23
- }, {
24
- capabilities: {
25
- tools: {},
26
- prompts: {},
27
- },
28
- });
29
- // Handle connection errors gracefully - don't crash on broken pipe
30
- server.onerror = (error) => {
31
- // Ignore broken pipe errors - they happen when the client disconnects
32
- const message = error instanceof Error ? error.message : String(error);
33
- if (message.includes('broken pipe') || message.includes('EPIPE')) {
34
- // Client disconnected, exit gracefully
35
- process.exit(0);
36
- }
37
- // For other errors, log to stderr (will be captured by MCP client)
38
- serverLogger.error(message);
39
- };
40
- // Handle connection close - exit gracefully
41
- server.onclose = () => {
42
- process.exit(0);
43
- };
44
- // Tool list handler - generated from registry
45
- server.setRequestHandler(ListToolsRequestSchema, async () => {
46
- return {
47
- tools: TOOLS.map((tool) => {
48
- return {
49
- name: tool.name,
50
- description: tool.description,
51
- inputSchema: zodToJsonSchema(tool.schema),
52
- annotations: tool.annotations,
53
- };
54
- }),
55
- };
56
- });
57
- /**
58
- * Convert a ToolResult to MCP content array.
59
- * Handles string (legacy), single content, and content arrays.
60
- */
61
- function toolResultToContent(result) {
62
- // Legacy string result - convert to text content
63
- if (typeof result === 'string') {
64
- return [{ type: 'text', text: result }];
65
- }
66
- // Array of content items
67
- if (Array.isArray(result)) {
68
- return result.map(contentToMcp);
69
- }
70
- // Single content item
71
- return [contentToMcp(result)];
72
- }
73
- /**
74
- * Convert a single ToolContent to MCP format.
75
- */
76
- function contentToMcp(content) {
77
- if (content.type === 'text') {
78
- return { type: 'text', text: content.text };
79
- }
80
- // Image content
81
- return { type: 'image', data: content.data, mimeType: content.mimeType };
82
- }
83
- // Tool call handler - generated from registry
84
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
85
- try {
86
- const tool = TOOL_MAP.get(request.params.name);
87
- if (!tool) {
88
- throw new Error(`Unknown tool: ${request.params.name}`);
89
- }
90
- const output = await tool.handler(request.params.arguments);
91
- return { content: toolResultToContent(output) };
92
- }
93
- catch (error) {
94
- const message = error instanceof Error ? error.message : String(error);
95
- return {
96
- content: [{ type: 'text', text: `Error: ${message}` }],
97
- isError: true,
98
- };
99
- }
100
- });
101
- // Prompt list handler - generated from registry
102
- server.setRequestHandler(ListPromptsRequestSchema, async () => {
103
- return {
104
- prompts: PROMPTS.map((prompt) => {
105
- return {
106
- name: prompt.name,
107
- description: prompt.description,
108
- arguments: prompt.arguments,
109
- };
110
- }),
111
- };
112
- });
113
- // Get prompt handler - returns prompt messages for a specific prompt
114
- server.setRequestHandler(GetPromptRequestSchema, async (request) => {
115
- const prompt = PROMPT_MAP.get(request.params.name);
116
- if (!prompt) {
117
- throw new Error(`Unknown prompt: ${request.params.name}`);
118
- }
119
- const args = (request.params.arguments || {});
120
- return {
121
- description: prompt.description,
122
- messages: prompt.handler(args),
123
- };
124
- });
125
- // Start server
126
11
  async function main() {
127
- const transport = new StdioServerTransport();
128
- await server.connect(transport);
129
- // Don't log to stderr - it interferes with MCP protocol
12
+ await startStdioServer({
13
+ name: 'mcp-server-tauri',
14
+ version: VERSION,
15
+ });
130
16
  }
131
17
  main().catch(() => {
132
18
  // Don't log errors to stderr - just exit silently
@@ -0,0 +1,16 @@
1
+ export interface McpLogger {
2
+ info: (...args: unknown[]) => void;
3
+ warn: (...args: unknown[]) => void;
4
+ error: (...args: unknown[]) => void;
5
+ }
6
+ /**
7
+ * Creates a logger that writes to stderr only.
8
+ *
9
+ * IMPORTANT: MCP uses stdio for JSON-RPC communication. The server sends
10
+ * JSON responses over stdout, and the client parses them. Any non-JSON
11
+ * output to stdout (like console.log) will corrupt the protocol and cause
12
+ * parsing errors like "invalid character 'M' looking for beginning of value".
13
+ *
14
+ * All logging MUST go to stderr to avoid interfering with MCP communication.
15
+ */
16
+ export declare function createMcpLogger(scope: string): McpLogger;
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod';
2
+ export declare const ListDevicesSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
3
+ export declare function listDevices(): Promise<{
4
+ android: string[];
5
+ ios: string[];
6
+ }>;
@@ -0,0 +1,32 @@
1
+ import { z } from 'zod';
2
+ export declare const ReadLogsSchema: z.ZodObject<{
3
+ source: z.ZodEnum<["console", "android", "ios", "system"]>;
4
+ lines: z.ZodDefault<z.ZodNumber>;
5
+ filter: z.ZodOptional<z.ZodString>;
6
+ since: z.ZodOptional<z.ZodString>;
7
+ windowId: z.ZodOptional<z.ZodString>;
8
+ appIdentifier: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
9
+ }, "strip", z.ZodTypeAny, {
10
+ lines: number;
11
+ source: "android" | "ios" | "console" | "system";
12
+ filter?: string | undefined;
13
+ windowId?: string | undefined;
14
+ appIdentifier?: string | number | undefined;
15
+ since?: string | undefined;
16
+ }, {
17
+ source: "android" | "ios" | "console" | "system";
18
+ filter?: string | undefined;
19
+ lines?: number | undefined;
20
+ windowId?: string | undefined;
21
+ appIdentifier?: string | number | undefined;
22
+ since?: string | undefined;
23
+ }>;
24
+ export interface ReadLogsOptions {
25
+ source: 'console' | 'android' | 'ios' | 'system';
26
+ lines?: number;
27
+ filter?: string;
28
+ since?: string;
29
+ windowId?: string;
30
+ appIdentifier?: string | number;
31
+ }
32
+ export declare function readLogs(options: ReadLogsOptions): Promise<string>;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Single source of truth for all MCP prompt definitions
3
+ * Prompts are user-controlled templates that appear as slash commands in MCP clients
4
+ */
5
+ export interface PromptArgument {
6
+ name: string;
7
+ description: string;
8
+ required?: boolean;
9
+ }
10
+ export interface PromptMessage {
11
+ role: 'user' | 'assistant';
12
+ content: {
13
+ type: 'text';
14
+ text: string;
15
+ };
16
+ }
17
+ export interface PromptDefinition {
18
+ name: string;
19
+ description: string;
20
+ arguments?: PromptArgument[];
21
+ handler: (args: Record<string, string>) => PromptMessage[];
22
+ }
23
+ /**
24
+ * Complete registry of all available prompts
25
+ */
26
+ export declare const PROMPTS: PromptDefinition[];
27
+ /**
28
+ * Create a Map for fast prompt lookup by name
29
+ */
30
+ export declare const PROMPT_MAP: Map<string, PromptDefinition>;
@@ -0,0 +1,13 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ export interface McpServerInfo {
3
+ name: string;
4
+ version: string;
5
+ }
6
+ export interface CliToolDefinition {
7
+ name: string;
8
+ description: string;
9
+ inputSchema: Record<string, unknown>;
10
+ }
11
+ export declare function getCliToolDefinitions(): CliToolDefinition[];
12
+ export declare function createMcpServer(info: McpServerInfo): Server;
13
+ export declare function startStdioServer(info: McpServerInfo): Promise<void>;
package/dist/server.js ADDED
@@ -0,0 +1,110 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
4
+ import { zodToJsonSchema } from 'zod-to-json-schema';
5
+ import { TOOLS, TOOL_MAP } from './tools-registry.js';
6
+ import { PROMPTS, PROMPT_MAP } from './prompts-registry.js';
7
+ import { createMcpLogger } from './logger.js';
8
+ /* eslint-disable no-process-exit */
9
+ const serverLogger = createMcpLogger('SERVER');
10
+ export function getCliToolDefinitions() {
11
+ return TOOLS.map((tool) => {
12
+ return {
13
+ name: tool.name,
14
+ description: tool.description,
15
+ inputSchema: zodToJsonSchema(tool.schema),
16
+ };
17
+ });
18
+ }
19
+ function toolResultToContent(result) {
20
+ if (typeof result === 'string') {
21
+ return [{ type: 'text', text: result }];
22
+ }
23
+ if (Array.isArray(result)) {
24
+ return result.map(contentToMcp);
25
+ }
26
+ return [contentToMcp(result)];
27
+ }
28
+ function contentToMcp(content) {
29
+ if (content.type === 'text') {
30
+ return { type: 'text', text: content.text };
31
+ }
32
+ return { type: 'image', data: content.data, mimeType: content.mimeType };
33
+ }
34
+ export function createMcpServer(info) {
35
+ const server = new Server({
36
+ name: info.name,
37
+ version: info.version,
38
+ }, {
39
+ capabilities: {
40
+ tools: {},
41
+ prompts: {},
42
+ },
43
+ });
44
+ server.onerror = (error) => {
45
+ const message = error instanceof Error ? error.message : String(error);
46
+ if (message.includes('broken pipe') || message.includes('EPIPE')) {
47
+ process.exit(0);
48
+ }
49
+ serverLogger.error(message);
50
+ };
51
+ server.onclose = () => {
52
+ process.exit(0);
53
+ };
54
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
55
+ return {
56
+ tools: TOOLS.map((tool) => {
57
+ return {
58
+ name: tool.name,
59
+ description: tool.description,
60
+ inputSchema: zodToJsonSchema(tool.schema),
61
+ annotations: tool.annotations,
62
+ };
63
+ }),
64
+ };
65
+ });
66
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
67
+ try {
68
+ const tool = TOOL_MAP.get(request.params.name);
69
+ if (!tool) {
70
+ throw new Error(`Unknown tool: ${request.params.name}`);
71
+ }
72
+ const output = await tool.handler(request.params.arguments);
73
+ return { content: toolResultToContent(output) };
74
+ }
75
+ catch (error) {
76
+ const message = error instanceof Error ? error.message : String(error);
77
+ return {
78
+ content: [{ type: 'text', text: `Error: ${message}` }],
79
+ isError: true,
80
+ };
81
+ }
82
+ });
83
+ server.setRequestHandler(ListPromptsRequestSchema, async () => {
84
+ return {
85
+ prompts: PROMPTS.map((prompt) => {
86
+ return {
87
+ name: prompt.name,
88
+ description: prompt.description,
89
+ arguments: prompt.arguments,
90
+ };
91
+ }),
92
+ };
93
+ });
94
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
95
+ const prompt = PROMPT_MAP.get(request.params.name);
96
+ if (!prompt) {
97
+ throw new Error(`Unknown prompt: ${request.params.name}`);
98
+ }
99
+ const args = (request.params.arguments || {});
100
+ return {
101
+ description: prompt.description,
102
+ messages: prompt.handler(args),
103
+ };
104
+ });
105
+ return server;
106
+ }
107
+ export async function startStdioServer(info) {
108
+ const transport = new StdioServerTransport(), server = createMcpServer(info);
109
+ await server.connect(transport);
110
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Single source of truth for all MCP tool definitions
3
+ * This file defines all available tools and their metadata
4
+ */
5
+ import { z } from 'zod';
6
+ /**
7
+ * Content types that tools can return.
8
+ * Text content is the default, image content is used for screenshots.
9
+ */
10
+ export interface TextContent {
11
+ type: 'text';
12
+ text: string;
13
+ }
14
+ export interface ImageContent {
15
+ type: 'image';
16
+ data: string;
17
+ mimeType: string;
18
+ }
19
+ export type ToolContent = TextContent | ImageContent;
20
+ /**
21
+ * Tool result can be a string (legacy, converted to TextContent) or structured content.
22
+ */
23
+ export type ToolResult = string | ToolContent | ToolContent[];
24
+ export type ToolHandler = (args: unknown) => Promise<ToolResult>;
25
+ /**
26
+ * Tool annotations that help the AI understand when and how to use tools.
27
+ * These follow the MCP specification for ToolAnnotations.
28
+ */
29
+ export interface ToolAnnotations {
30
+ title?: string;
31
+ readOnlyHint?: boolean;
32
+ destructiveHint?: boolean;
33
+ idempotentHint?: boolean;
34
+ openWorldHint?: boolean;
35
+ }
36
+ export interface ToolDefinition {
37
+ name: string;
38
+ description: string;
39
+ category: string;
40
+ schema: z.ZodSchema;
41
+ handler: ToolHandler;
42
+ annotations?: ToolAnnotations;
43
+ }
44
+ /**
45
+ * Tool categories for organization
46
+ */
47
+ export declare const TOOL_CATEGORIES: {
48
+ readonly SETUP: "Setup & Configuration";
49
+ readonly MOBILE_DEVELOPMENT: "Mobile Development";
50
+ readonly UI_AUTOMATION: "UI Automation & WebView Interaction";
51
+ readonly IPC_PLUGIN: "IPC & Plugin Tools (via MCP Bridge)";
52
+ };
53
+ /**
54
+ * Complete registry of all available tools
55
+ * This is the single source of truth for tool definitions
56
+ */
57
+ export declare const TOOLS: ToolDefinition[];
58
+ /**
59
+ * Get all tool names for type checking
60
+ */
61
+ export type ToolName = typeof TOOLS[number]['name'];
62
+ /**
63
+ * Get tools grouped by category
64
+ */
65
+ export declare function getToolsByCategory(): Record<string, ToolDefinition[]>;
66
+ /**
67
+ * Get total tool count
68
+ */
69
+ export declare function getToolCount(): number;
70
+ /**
71
+ * Create a Map for fast tool lookup by name
72
+ */
73
+ export declare const TOOL_MAP: Map<string, ToolDefinition>;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Window type definitions for multi-webview support.
3
+ */
4
+ /**
5
+ * Information about a webview window.
6
+ */
7
+ export interface WindowInfo {
8
+ label: string;
9
+ title?: string;
10
+ url?: string;
11
+ focused: boolean;
12
+ visible: boolean;
13
+ isMain: boolean;
14
+ }
15
+ /**
16
+ * Response from the list_windows command.
17
+ */
18
+ export interface ListWindowsResponse {
19
+ windows: WindowInfo[];
20
+ defaultWindow: string;
21
+ totalCount: number;
22
+ }
23
+ /**
24
+ * Context about which window was used for an operation.
25
+ */
26
+ export interface WindowContext {
27
+ windowLabel: string;
28
+ totalWindows: number;
29
+ warning?: string;
30
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Version information for the MCP Bridge plugin.
3
+ *
4
+ * Reads the version from this package's package.json at runtime.
5
+ * Both packages share the same version (monorepo single-version policy).
6
+ */
7
+ /**
8
+ * Full version string (e.g., "0.6.5")
9
+ */
10
+ export declare const PLUGIN_VERSION_FULL: string;
11
+ /**
12
+ * Cargo-compatible version string for Cargo.toml dependencies (e.g., "0.6")
13
+ * This is the major.minor version used in Cargo.toml dependency specifications.
14
+ */
15
+ export declare const PLUGIN_VERSION_CARGO: string;
package/package.json CHANGED
@@ -1,9 +1,17 @@
1
1
  {
2
2
  "name": "@hypothesi/tauri-mcp-server",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "mcpName": "io.github.hypothesi/mcp-server-tauri",
5
5
  "description": "A Model Context Protocol server for use with Tauri v2 applications",
6
6
  "type": "module",
7
+ "main": "./dist/api.js",
8
+ "types": "./dist/api.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/api.js",
12
+ "types": "./dist/api.d.ts"
13
+ }
14
+ },
7
15
  "bin": {
8
16
  "mcp-server-tauri": "./dist/index.js"
9
17
  },