mirror of
https://github.com/eyaltoledano/claude-task-master.git
synced 2026-01-30 06:12:05 +00:00
feat: add @tm/ai-tools package with Context7 MCP integration
Adds a new package @tm/ai-tools that provides AI SDK tool integrations
for Task Master. Starts with Context7 MCP support for documentation
lookup capabilities.
Package features:
- createContext7Tools() - Creates MCP client for Context7 documentation
- createMCPTools() - Auto-detects and combines available MCP tools
- isContext7Available() - Checks if CONTEXT7_API_KEY is configured
- getAvailableMCPTools() - Lists available MCP tool sources
Usage:
import { createContext7Tools } from '@tm/ai-tools/context7';
import { createMCPTools } from '@tm/ai-tools';
The package uses @ai-sdk/mcp for MCP client functionality.
This commit is contained in:
11943
package-lock.json
generated
11943
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
37
packages/ai-sdk-tools/package.json
Normal file
37
packages/ai-sdk-tools/package.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "@tm/ai-tools",
|
||||
"private": true,
|
||||
"description": "AI SDK tools for Task Master - MCP integrations and AI utilities",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"main": "./dist/index.js",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./context7": "./src/context7/index.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"lint": "biome check --write",
|
||||
"lint:check": "biome check",
|
||||
"lint:fix": "biome check --fix --unsafe",
|
||||
"format": "biome format --write",
|
||||
"format:check": "biome format",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ai-sdk/mcp": "^0.0.10",
|
||||
"ai": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.10.5",
|
||||
"@vitest/coverage-v8": "^4.0.10",
|
||||
"typescript": "^5.9.2",
|
||||
"vitest": "^4.0.10"
|
||||
},
|
||||
"files": ["src", "README.md", "CHANGELOG.md"],
|
||||
"keywords": ["ai-sdk", "mcp", "context7", "task-master", "ai-tools"],
|
||||
"author": "Task Master AI",
|
||||
"version": ""
|
||||
}
|
||||
94
packages/ai-sdk-tools/src/context7/client.ts
Normal file
94
packages/ai-sdk-tools/src/context7/client.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { experimental_createMCPClient } from '@ai-sdk/mcp';
|
||||
import { Experimental_StdioMCPTransport } from '@ai-sdk/mcp/mcp-stdio';
|
||||
import type {
|
||||
Context7Config,
|
||||
Context7ToolsOptions,
|
||||
Context7ToolsResult
|
||||
} from './types.js';
|
||||
|
||||
/**
|
||||
* Error thrown when Context7 API key is not configured
|
||||
*/
|
||||
export class Context7ApiKeyError extends Error {
|
||||
constructor() {
|
||||
super(
|
||||
'Context7 API key is required. Set CONTEXT7_API_KEY environment variable or pass apiKey in config.'
|
||||
);
|
||||
this.name = 'Context7ApiKeyError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Context7 API key from config or environment
|
||||
*/
|
||||
function getApiKey(config?: Context7Config): string {
|
||||
const apiKey = config?.apiKey ?? process.env.CONTEXT7_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Context7ApiKeyError();
|
||||
}
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Context7 MCP client and returns tools for use with AI SDK.
|
||||
*
|
||||
* Context7 provides up-to-date documentation and code examples for libraries
|
||||
* and frameworks, helping AI models give more accurate answers about APIs.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { createContext7Tools } from '@tm/ai-tools/context7';
|
||||
* import { generateText } from 'ai';
|
||||
* import { openai } from '@ai-sdk/openai';
|
||||
*
|
||||
* const { tools, close } = await createContext7Tools();
|
||||
*
|
||||
* try {
|
||||
* const result = await generateText({
|
||||
* model: openai('gpt-4o'),
|
||||
* tools,
|
||||
* prompt: 'How do I use the latest React Query API?',
|
||||
* });
|
||||
* console.log(result.text);
|
||||
* } finally {
|
||||
* await close();
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export async function createContext7Tools(
|
||||
options?: Context7ToolsOptions
|
||||
): Promise<Context7ToolsResult> {
|
||||
const apiKey = getApiKey(options?.config);
|
||||
|
||||
const transport = new Experimental_StdioMCPTransport({
|
||||
command: 'npx',
|
||||
args: ['-y', '@upstash/context7-mcp', '--api-key', apiKey]
|
||||
});
|
||||
|
||||
const client = await experimental_createMCPClient({
|
||||
transport
|
||||
});
|
||||
|
||||
options?.onReady?.();
|
||||
|
||||
const tools = await client.tools();
|
||||
|
||||
return {
|
||||
tools,
|
||||
close: async () => {
|
||||
await client.close();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Context7 is available (API key is configured)
|
||||
*/
|
||||
export function isContext7Available(config?: Context7Config): boolean {
|
||||
try {
|
||||
getApiKey(config);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
11
packages/ai-sdk-tools/src/context7/index.ts
Normal file
11
packages/ai-sdk-tools/src/context7/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export {
|
||||
createContext7Tools,
|
||||
isContext7Available,
|
||||
Context7ApiKeyError
|
||||
} from './client.js';
|
||||
|
||||
export type {
|
||||
Context7Config,
|
||||
Context7ToolsOptions,
|
||||
Context7ToolsResult
|
||||
} from './types.js';
|
||||
45
packages/ai-sdk-tools/src/context7/types.ts
Normal file
45
packages/ai-sdk-tools/src/context7/types.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Configuration options for the Context7 MCP client
|
||||
*/
|
||||
export interface Context7Config {
|
||||
/**
|
||||
* The Context7 API key. If not provided, will attempt to read from
|
||||
* CONTEXT7_API_KEY environment variable.
|
||||
*/
|
||||
apiKey?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for creating Context7 tools
|
||||
*/
|
||||
export interface Context7ToolsOptions {
|
||||
/**
|
||||
* Configuration for the Context7 client
|
||||
*/
|
||||
config?: Context7Config;
|
||||
|
||||
/**
|
||||
* Callback when the client is ready
|
||||
*/
|
||||
onReady?: () => void;
|
||||
|
||||
/**
|
||||
* Callback when an error occurs
|
||||
*/
|
||||
onError?: (error: Error) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Result from creating Context7 tools
|
||||
*/
|
||||
export interface Context7ToolsResult {
|
||||
/**
|
||||
* The tools object that can be passed to AI SDK's generateText/streamText
|
||||
*/
|
||||
tools: Record<string, unknown>;
|
||||
|
||||
/**
|
||||
* Close the MCP client connection. Should be called when done using the tools.
|
||||
*/
|
||||
close: () => Promise<void>;
|
||||
}
|
||||
25
packages/ai-sdk-tools/src/index.ts
Normal file
25
packages/ai-sdk-tools/src/index.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @tm/ai-tools - AI SDK tools for Task Master
|
||||
*
|
||||
* This package provides AI SDK integrations for various MCP servers and tools.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Import Context7 tools directly
|
||||
* import { createContext7Tools } from '@tm/ai-tools/context7';
|
||||
*
|
||||
* // Or use the MCP tools manager for auto-detection
|
||||
* import { createMCPTools } from '@tm/ai-tools';
|
||||
* ```
|
||||
*/
|
||||
|
||||
// MCP Tools Manager - auto-detects and combines available MCP tools
|
||||
export {
|
||||
createMCPTools,
|
||||
getAvailableMCPTools,
|
||||
type MCPToolsManagerConfig,
|
||||
type MCPToolsResult
|
||||
} from './mcp-tools-manager.js';
|
||||
|
||||
// Re-export context7 module for convenience
|
||||
export * from './context7/index.js';
|
||||
126
packages/ai-sdk-tools/src/mcp-tools-manager.ts
Normal file
126
packages/ai-sdk-tools/src/mcp-tools-manager.ts
Normal file
@@ -0,0 +1,126 @@
|
||||
import {
|
||||
createContext7Tools,
|
||||
isContext7Available,
|
||||
type Context7Config
|
||||
} from './context7/index.js';
|
||||
|
||||
/**
|
||||
* Configuration for MCP tools manager
|
||||
*/
|
||||
export interface MCPToolsManagerConfig {
|
||||
/**
|
||||
* Enable Context7 tools for documentation lookup
|
||||
*/
|
||||
context7?: Context7Config | boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Result from getting MCP tools
|
||||
*/
|
||||
export interface MCPToolsResult {
|
||||
/**
|
||||
* Combined tools from all enabled MCP servers
|
||||
*/
|
||||
tools: Record<string, unknown>;
|
||||
|
||||
/**
|
||||
* Close all MCP client connections. Should be called when done.
|
||||
*/
|
||||
close: () => Promise<void>;
|
||||
|
||||
/**
|
||||
* List of enabled MCP tool sources
|
||||
*/
|
||||
enabledSources: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and manages MCP tools from multiple sources.
|
||||
*
|
||||
* This utility automatically detects available MCP tools based on
|
||||
* environment variables and configuration.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { createMCPTools } from '@tm/ai-tools';
|
||||
* import { generateText } from 'ai';
|
||||
* import { openai } from '@ai-sdk/openai';
|
||||
*
|
||||
* // Auto-detect available tools from environment
|
||||
* const { tools, close, enabledSources } = await createMCPTools();
|
||||
*
|
||||
* console.log('Enabled MCP tools:', enabledSources);
|
||||
*
|
||||
* try {
|
||||
* const result = await generateText({
|
||||
* model: openai('gpt-4o'),
|
||||
* tools,
|
||||
* prompt: 'How do I use React Query?',
|
||||
* });
|
||||
* console.log(result.text);
|
||||
* } finally {
|
||||
* await close();
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // With explicit configuration
|
||||
* const { tools, close } = await createMCPTools({
|
||||
* context7: { apiKey: 'my-api-key' },
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export async function createMCPTools(
|
||||
config?: MCPToolsManagerConfig
|
||||
): Promise<MCPToolsResult> {
|
||||
const tools: Record<string, unknown> = {};
|
||||
const closeFunctions: (() => Promise<void>)[] = [];
|
||||
const enabledSources: string[] = [];
|
||||
|
||||
// Context7 tools
|
||||
const context7Config =
|
||||
config?.context7 === true
|
||||
? {}
|
||||
: config?.context7 === false
|
||||
? undefined
|
||||
: config?.context7;
|
||||
|
||||
// Only create Context7 tools if explicitly enabled or auto-detect available
|
||||
const shouldEnableContext7 =
|
||||
config?.context7 !== false &&
|
||||
(config?.context7 !== undefined || isContext7Available(context7Config));
|
||||
|
||||
if (shouldEnableContext7 && isContext7Available(context7Config)) {
|
||||
try {
|
||||
const context7 = await createContext7Tools({ config: context7Config });
|
||||
Object.assign(tools, context7.tools);
|
||||
closeFunctions.push(context7.close);
|
||||
enabledSources.push('context7');
|
||||
} catch (error) {
|
||||
// Log but don't fail if Context7 connection fails
|
||||
console.warn('Failed to connect to Context7 MCP server:', error);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
tools,
|
||||
enabledSources,
|
||||
close: async () => {
|
||||
await Promise.all(closeFunctions.map((fn) => fn()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check which MCP tools are available based on environment
|
||||
*/
|
||||
export function getAvailableMCPTools(): string[] {
|
||||
const available: string[] = [];
|
||||
|
||||
if (isContext7Available()) {
|
||||
available.push('context7');
|
||||
}
|
||||
|
||||
return available;
|
||||
}
|
||||
36
packages/ai-sdk-tools/tsconfig.json
Normal file
36
packages/ai-sdk-tools/tsconfig.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"lib": ["ES2022"],
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
"baseUrl": ".",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"strictFunctionTypes": true,
|
||||
"strictBindCallApply": true,
|
||||
"strictPropertyInitialization": true,
|
||||
"noImplicitThis": true,
|
||||
"alwaysStrict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"moduleResolution": "NodeNext",
|
||||
"moduleDetection": "force",
|
||||
"types": ["node"],
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"allowImportingTsExtensions": false
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "tests", "**/*.test.ts", "**/*.spec.ts"]
|
||||
}
|
||||
@@ -29,7 +29,9 @@
|
||||
"./packages/ai-sdk-provider-grok-cli/src/*"
|
||||
],
|
||||
"@tm/bridge": ["./packages/tm-bridge/src/index.ts"],
|
||||
"@tm/bridge/*": ["./packages/tm-bridge/src/*"]
|
||||
"@tm/bridge/*": ["./packages/tm-bridge/src/*"],
|
||||
"@tm/ai-tools": ["./packages/ai-sdk-tools/src/index.ts"],
|
||||
"@tm/ai-tools/*": ["./packages/ai-sdk-tools/src/*"]
|
||||
}
|
||||
},
|
||||
"tsx": {
|
||||
|
||||
Reference in New Issue
Block a user