Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions core/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "@modelcontextprotocol/inspector-core",
"version": "0.1.0",
"description": "Core MCP client logic for Inspector - no React dependencies",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./types": {
"types": "./dist/types/index.d.ts",
"import": "./dist/types/index.js"
}
},
"scripts": {
"build": "tsc",
"clean": "rm -rf dist",
"prepublishOnly": "npm run build"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.25.1"
},
"devDependencies": {
"typescript": "^5.6.3"
},
"files": [
"dist",
"src"
]
}
154 changes: 154 additions & 0 deletions core/src/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/**
* MCP Client Wrapper - Manage MCP client lifecycle and capabilities
*
* This module wraps the MCP SDK Client for React usage, handling:
* - Client creation with proper capabilities
* - Connection lifecycle (connect/disconnect)
* - Server info extraction
*
* Usage:
* import { createMcpClient, connectClient } from '@/lib/mcp/client';
*
* const client = createMcpClient();
* const transport = createHttpTransport(url);
* await connectClient(client, transport);
*/

import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
import type { Implementation, ServerCapabilities } from '@modelcontextprotocol/sdk/types.js';

/**
* Client configuration options.
*/
export interface McpClientOptions {
/** Client name shown to servers */
name?: string;
/** Client version */
version?: string;
/** Enable sampling capability (receive LLM requests from server) */
enableSampling?: boolean;
/** Enable roots capability (expose filesystem paths to server) */
enableRoots?: boolean;
}

/**
* Information about a connected MCP server.
*/
export interface ServerInfo {
/** Server name */
name: string;
/** Server version */
version: string;
/** Server capabilities */
capabilities: ServerCapabilities;
/** Server instructions (if provided) */
instructions?: string;
}

const DEFAULT_CLIENT_NAME = 'MCP Inspector';
const DEFAULT_CLIENT_VERSION = '2.0.0';

/**
* Create a new MCP client with Inspector capabilities.
*
* @param options - Client configuration options
* @returns Configured MCP Client instance
*/
export function createMcpClient(options: McpClientOptions = {}): Client {
const {
name = DEFAULT_CLIENT_NAME,
version = DEFAULT_CLIENT_VERSION,
enableSampling = true,
enableRoots = true,
} = options;

const clientInfo: Implementation = {
name,
version,
};

// Build capabilities based on options
const capabilities: Record<string, unknown> = {};

if (enableSampling) {
// Declare sampling capability with tool support (per MCP 2025-11-25 spec)
capabilities.sampling = { tools: {} };
}

if (enableRoots) {
// Declare roots capability
capabilities.roots = { listChanged: true };
}

return new Client(clientInfo, { capabilities });
}

/**
* Connect an MCP client to a server via transport.
*
* @param client - MCP Client instance
* @param transport - Transport to connect through
* @returns Server information on successful connection
* @throws Error if connection fails
*/
export async function connectClient(
client: Client,
transport: Transport
): Promise<ServerInfo> {
await client.connect(transport);

const serverVersion = client.getServerVersion();
const serverCapabilities = client.getServerCapabilities();
const instructions = client.getInstructions();

if (!serverVersion) {
throw new Error('Failed to get server version after connection');
}

return {
name: serverVersion.name,
version: serverVersion.version,
capabilities: serverCapabilities ?? {},
instructions: instructions ?? undefined,
};
}

/**
* Disconnect an MCP client and clean up resources.
*
* @param client - MCP Client instance to disconnect
*/
export async function disconnectClient(client: Client): Promise<void> {
await client.close();
}

/**
* Check if a client is currently connected.
*
* @param client - MCP Client instance
* @returns true if connected
*/
export function isClientConnected(client: Client): boolean {
// The SDK client doesn't expose connection state directly,
// but we can check if server version is available
try {
return client.getServerVersion() !== undefined;
} catch {
return false;
}
}

/**
* Check if server supports a specific capability.
*
* @param serverInfo - Server info from connection
* @param capability - Capability name to check
* @returns true if capability is supported
*/
export function serverSupports(
serverInfo: ServerInfo,
capability: keyof ServerCapabilities
): boolean {
return serverInfo.capabilities[capability] !== undefined;
}
44 changes: 44 additions & 0 deletions core/src/data/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Data Layer Interfaces and Memory Stubs
*
* This module provides:
* - Repository interfaces for data storage (CRUD contracts)
* - Service interfaces for stateful business logic
* - Memory stub implementations for development/testing
*
* Real implementations (proxy API, file-based, localStorage) can be added later.
*/

// Repository interfaces
export type {
ServerConfigRepository,
HistoryRepository,
HistoryListOptions,
LogsRepository,
LogsListOptions,
TestingProfileRepository,
} from './repositories.js';

// Service interfaces
export type {
ConnectionService,
ConnectionState,
ConnectionError,
ConnectionOptions,
ExecutionService,
ExecutionState,
PendingClientRequest,
} from './services.js';

// Initial state exports
export { initialConnectionState, initialExecutionState } from './services.js';

// Memory stub implementations
export {
createMemoryServerConfigRepository,
createMemoryHistoryRepository,
createMemoryLogsRepository,
createMemoryTestingProfileRepository,
createMemoryConnectionService,
createMemoryExecutionService,
} from './memory.js';
Loading