toonify-mcp 0.1.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 ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Claude Code Toonify MCP Server
4
+ *
5
+ * Optimizes token usage by converting structured data to TOON format
6
+ * before sending to Claude API, achieving 60%+ token reduction.
7
+ */
8
+ import { ToonifyMCPServer } from './server/mcp-server.js';
9
+ async function main() {
10
+ const server = new ToonifyMCPServer();
11
+ try {
12
+ await server.start();
13
+ }
14
+ catch (error) {
15
+ console.error('Failed to start Toonify MCP server:', error);
16
+ process.exit(1);
17
+ }
18
+ }
19
+ main();
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;IAEtC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * MetricsCollector: Local-only metrics tracking
3
+ */
4
+ import type { TokenStats } from '../optimizer/types.js';
5
+ export interface OptimizationMetric {
6
+ timestamp: string;
7
+ toolName: string;
8
+ originalTokens: number;
9
+ optimizedTokens: number;
10
+ savings: number;
11
+ savingsPercentage: number;
12
+ wasOptimized: boolean;
13
+ format?: string;
14
+ reason?: string;
15
+ }
16
+ export declare class MetricsCollector {
17
+ private statsPath;
18
+ constructor();
19
+ /**
20
+ * Record an optimization attempt
21
+ */
22
+ record(metric: OptimizationMetric): Promise<void>;
23
+ /**
24
+ * Get current statistics
25
+ */
26
+ getStats(): Promise<TokenStats>;
27
+ /**
28
+ * Load stats from disk
29
+ */
30
+ private loadStats;
31
+ /**
32
+ * Save stats to disk
33
+ */
34
+ private saveStats;
35
+ /**
36
+ * Format stats as dashboard
37
+ */
38
+ formatDashboard(): Promise<string>;
39
+ }
40
+ //# sourceMappingURL=metrics-collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-collector.d.ts","sourceRoot":"","sources":["../../src/metrics/metrics-collector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAS;;IAW1B;;OAEG;IACG,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BvD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC;IAIrC;;OAEG;YACW,SAAS;IAoBvB;;OAEG;YACW,SAAS;IAQvB;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;CAiBzC"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * MetricsCollector: Local-only metrics tracking
3
+ */
4
+ import { promises as fs } from 'fs';
5
+ import path from 'path';
6
+ import os from 'os';
7
+ export class MetricsCollector {
8
+ statsPath;
9
+ constructor() {
10
+ // Store in user's home directory, not in project
11
+ this.statsPath = path.join(os.homedir(), '.claude', 'token_stats.json');
12
+ }
13
+ /**
14
+ * Record an optimization attempt
15
+ */
16
+ async record(metric) {
17
+ try {
18
+ const stats = await this.loadStats();
19
+ // Update aggregated stats
20
+ stats.totalRequests++;
21
+ if (metric.wasOptimized) {
22
+ stats.optimizedRequests++;
23
+ }
24
+ stats.tokensBeforeOptimization += metric.originalTokens;
25
+ stats.tokensAfterOptimization += metric.optimizedTokens;
26
+ stats.totalSavings += metric.savings;
27
+ // Recalculate average
28
+ stats.averageSavingsPercentage =
29
+ stats.optimizedRequests > 0
30
+ ? (stats.totalSavings / stats.tokensBeforeOptimization) * 100
31
+ : 0;
32
+ await this.saveStats(stats);
33
+ }
34
+ catch (error) {
35
+ // Silent failure - metrics should never break functionality
36
+ console.error('Failed to record metrics:', error);
37
+ }
38
+ }
39
+ /**
40
+ * Get current statistics
41
+ */
42
+ async getStats() {
43
+ return await this.loadStats();
44
+ }
45
+ /**
46
+ * Load stats from disk
47
+ */
48
+ async loadStats() {
49
+ try {
50
+ // Ensure directory exists
51
+ await fs.mkdir(path.dirname(this.statsPath), { recursive: true });
52
+ const data = await fs.readFile(this.statsPath, 'utf-8');
53
+ return JSON.parse(data);
54
+ }
55
+ catch {
56
+ // Return empty stats if file doesn't exist
57
+ return {
58
+ totalRequests: 0,
59
+ optimizedRequests: 0,
60
+ tokensBeforeOptimization: 0,
61
+ tokensAfterOptimization: 0,
62
+ totalSavings: 0,
63
+ averageSavingsPercentage: 0,
64
+ };
65
+ }
66
+ }
67
+ /**
68
+ * Save stats to disk
69
+ */
70
+ async saveStats(stats) {
71
+ await fs.writeFile(this.statsPath, JSON.stringify(stats, null, 2), 'utf-8');
72
+ }
73
+ /**
74
+ * Format stats as dashboard
75
+ */
76
+ async formatDashboard() {
77
+ const stats = await this.getStats();
78
+ return `
79
+ 📊 Token Optimization Stats
80
+ ━━━━━━━━━━━━━━━━━━━━━━━━
81
+ Total Requests: ${stats.totalRequests}
82
+ Optimized: ${stats.optimizedRequests} (${((stats.optimizedRequests / stats.totalRequests) * 100).toFixed(1)}%)
83
+
84
+ Tokens Before: ${stats.tokensBeforeOptimization.toLocaleString()}
85
+ Tokens After: ${stats.tokensAfterOptimization.toLocaleString()}
86
+ Total Savings: ${stats.totalSavings.toLocaleString()} (${stats.averageSavingsPercentage.toFixed(1)}%)
87
+
88
+ 💰 Cost Savings (at $3/1M input tokens):
89
+ $${((stats.totalSavings / 1_000_000) * 3).toFixed(2)} saved
90
+ `.trim();
91
+ }
92
+ }
93
+ //# sourceMappingURL=metrics-collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-collector.js","sourceRoot":"","sources":["../../src/metrics/metrics-collector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * TokenOptimizer: Core optimization logic using Toonify
3
+ */
4
+ import type { OptimizationResult, ToolMetadata, OptimizationConfig } from './types.js';
5
+ export declare class TokenOptimizer {
6
+ private config;
7
+ private tokenEncoder;
8
+ constructor(config?: Partial<OptimizationConfig>);
9
+ /**
10
+ * Main optimization method
11
+ */
12
+ optimize(content: string, metadata?: ToolMetadata): Promise<OptimizationResult>;
13
+ /**
14
+ * Detect if content is structured data (JSON/CSV/YAML)
15
+ */
16
+ private detectStructuredData;
17
+ /**
18
+ * Simple CSV detection heuristic
19
+ */
20
+ private looksLikeCSV;
21
+ /**
22
+ * Parse simple CSV to array of objects
23
+ */
24
+ private parseSimpleCSV;
25
+ /**
26
+ * Count tokens in text
27
+ */
28
+ private countTokens;
29
+ /**
30
+ * Check if tool should be skipped
31
+ */
32
+ private shouldSkipTool;
33
+ }
34
+ //# sourceMappingURL=token-optimizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-optimizer.d.ts","sourceRoot":"","sources":["../../src/optimizer/token-optimizer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EAEZ,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,YAAY,CAAC;gBAET,MAAM,GAAE,OAAO,CAAC,kBAAkB,CAAM;IAcpD;;OAEG;IACG,QAAQ,CACZ,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,YAAY,GACtB,OAAO,CAAC,kBAAkB,CAAC;IA2F9B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA4B5B;;OAEG;IACH,OAAO,CAAC,YAAY;IAiBpB;;OAEG;IACH,OAAO,CAAC,cAAc;IActB;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,OAAO,CAAC,cAAc;CAMvB"}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * TokenOptimizer: Core optimization logic using Toonify
3
+ */
4
+ import { encode as toonEncode } from '@toon-format/toon';
5
+ import { encoding_for_model } from 'tiktoken';
6
+ import yaml from 'yaml';
7
+ export class TokenOptimizer {
8
+ config;
9
+ tokenEncoder;
10
+ constructor(config = {}) {
11
+ this.config = {
12
+ enabled: true,
13
+ minTokensThreshold: 50,
14
+ minSavingsThreshold: 30,
15
+ maxProcessingTime: 50,
16
+ skipToolPatterns: [],
17
+ ...config
18
+ };
19
+ // Use Claude tokenizer
20
+ this.tokenEncoder = encoding_for_model('gpt-4');
21
+ }
22
+ /**
23
+ * Main optimization method
24
+ */
25
+ async optimize(content, metadata) {
26
+ const startTime = Date.now();
27
+ // Quick path: skip if disabled or content too small
28
+ if (!this.config.enabled || content.length < 200) {
29
+ return {
30
+ optimized: false,
31
+ originalContent: content,
32
+ originalTokens: this.countTokens(content),
33
+ reason: 'Content too small'
34
+ };
35
+ }
36
+ // Skip if tool matches skip patterns
37
+ if (metadata?.toolName && this.shouldSkipTool(metadata.toolName)) {
38
+ return {
39
+ optimized: false,
40
+ originalContent: content,
41
+ originalTokens: this.countTokens(content),
42
+ reason: `Tool ${metadata.toolName} in skip list`
43
+ };
44
+ }
45
+ // Detect structured data
46
+ const structuredData = this.detectStructuredData(content);
47
+ if (!structuredData) {
48
+ return {
49
+ optimized: false,
50
+ originalContent: content,
51
+ originalTokens: this.countTokens(content),
52
+ reason: 'Not structured data'
53
+ };
54
+ }
55
+ try {
56
+ // Convert to TOON format
57
+ const toonContent = toonEncode(structuredData.data);
58
+ // Count tokens
59
+ const originalTokens = this.countTokens(content);
60
+ const optimizedTokens = this.countTokens(toonContent);
61
+ // Calculate savings
62
+ const tokenSavings = originalTokens - optimizedTokens;
63
+ const savingsPercentage = (tokenSavings / originalTokens) * 100;
64
+ // Check if worth using
65
+ if (savingsPercentage < this.config.minSavingsThreshold) {
66
+ return {
67
+ optimized: false,
68
+ originalContent: content,
69
+ originalTokens,
70
+ reason: `Savings too low: ${savingsPercentage.toFixed(1)}%`
71
+ };
72
+ }
73
+ // Check processing time
74
+ const elapsed = Date.now() - startTime;
75
+ if (elapsed > this.config.maxProcessingTime) {
76
+ return {
77
+ optimized: false,
78
+ originalContent: content,
79
+ originalTokens,
80
+ reason: `Processing timeout: ${elapsed}ms`
81
+ };
82
+ }
83
+ return {
84
+ optimized: true,
85
+ originalContent: content,
86
+ optimizedContent: toonContent,
87
+ originalTokens,
88
+ optimizedTokens,
89
+ savings: {
90
+ tokens: tokenSavings,
91
+ percentage: savingsPercentage
92
+ },
93
+ format: structuredData.type
94
+ };
95
+ }
96
+ catch (error) {
97
+ // Silent fallback on error
98
+ return {
99
+ optimized: false,
100
+ originalContent: content,
101
+ originalTokens: this.countTokens(content),
102
+ reason: `Error: ${error instanceof Error ? error.message : 'Unknown'}`
103
+ };
104
+ }
105
+ }
106
+ /**
107
+ * Detect if content is structured data (JSON/CSV/YAML)
108
+ */
109
+ detectStructuredData(content) {
110
+ // Try JSON first
111
+ try {
112
+ const data = JSON.parse(content);
113
+ if (typeof data === 'object' && data !== null) {
114
+ return { type: 'json', data, confidence: 1.0 };
115
+ }
116
+ }
117
+ catch { }
118
+ // Try YAML
119
+ try {
120
+ const data = yaml.parse(content);
121
+ if (typeof data === 'object' && data !== null) {
122
+ return { type: 'yaml', data, confidence: 0.9 };
123
+ }
124
+ }
125
+ catch { }
126
+ // Try CSV (simple heuristic)
127
+ if (this.looksLikeCSV(content)) {
128
+ try {
129
+ const data = this.parseSimpleCSV(content);
130
+ return { type: 'csv', data, confidence: 0.8 };
131
+ }
132
+ catch { }
133
+ }
134
+ return null;
135
+ }
136
+ /**
137
+ * Simple CSV detection heuristic
138
+ */
139
+ looksLikeCSV(content) {
140
+ const lines = content.split('\n').filter(l => l.trim());
141
+ if (lines.length < 2)
142
+ return false;
143
+ const firstLineCommas = (lines[0].match(/,/g) || []).length;
144
+ if (firstLineCommas === 0)
145
+ return false;
146
+ // Check if most lines have similar comma count
147
+ let matchingLines = 0;
148
+ for (let i = 1; i < Math.min(lines.length, 10); i++) {
149
+ const commas = (lines[i].match(/,/g) || []).length;
150
+ if (commas === firstLineCommas)
151
+ matchingLines++;
152
+ }
153
+ return matchingLines >= Math.min(lines.length - 1, 7);
154
+ }
155
+ /**
156
+ * Parse simple CSV to array of objects
157
+ */
158
+ parseSimpleCSV(content) {
159
+ const lines = content.split('\n').filter(l => l.trim());
160
+ const headers = lines[0].split(',').map(h => h.trim());
161
+ return lines.slice(1).map(line => {
162
+ const values = line.split(',').map(v => v.trim());
163
+ const obj = {};
164
+ headers.forEach((header, i) => {
165
+ obj[header] = values[i] || '';
166
+ });
167
+ return obj;
168
+ });
169
+ }
170
+ /**
171
+ * Count tokens in text
172
+ */
173
+ countTokens(text) {
174
+ return this.tokenEncoder.encode(text).length;
175
+ }
176
+ /**
177
+ * Check if tool should be skipped
178
+ */
179
+ shouldSkipTool(toolName) {
180
+ return this.config.skipToolPatterns?.some(pattern => {
181
+ const regex = new RegExp(pattern);
182
+ return regex.test(toolName);
183
+ }) ?? false;
184
+ }
185
+ }
186
+ //# sourceMappingURL=token-optimizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-optimizer.js","sourceRoot":"","sources":["../../src/optimizer/token-optimizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Type definitions for token optimization
3
+ */
4
+ export interface OptimizationResult {
5
+ optimized: boolean;
6
+ originalContent: string;
7
+ optimizedContent?: string;
8
+ originalTokens: number;
9
+ optimizedTokens?: number;
10
+ savings?: {
11
+ tokens: number;
12
+ percentage: number;
13
+ };
14
+ format?: 'json' | 'csv' | 'yaml' | 'unknown';
15
+ reason?: string;
16
+ }
17
+ export interface ToolMetadata {
18
+ toolName: string;
19
+ contentType?: string;
20
+ size: number;
21
+ }
22
+ export interface StructuredData {
23
+ type: 'json' | 'csv' | 'yaml';
24
+ data: any;
25
+ confidence: number;
26
+ }
27
+ export interface OptimizationConfig {
28
+ enabled: boolean;
29
+ minTokensThreshold: number;
30
+ minSavingsThreshold: number;
31
+ maxProcessingTime: number;
32
+ skipToolPatterns?: string[];
33
+ }
34
+ export interface TokenStats {
35
+ totalRequests: number;
36
+ optimizedRequests: number;
37
+ tokensBeforeOptimization: number;
38
+ tokensAfterOptimization: number;
39
+ totalSavings: number;
40
+ averageSavingsPercentage: number;
41
+ }
42
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/optimizer/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;IAC9B,IAAI,EAAE,GAAG,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,wBAAwB,EAAE,MAAM,CAAC;IACjC,uBAAuB,EAAE,MAAM,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,wBAAwB,EAAE,MAAM,CAAC;CAClC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Type definitions for token optimization
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/optimizer/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * ToonifyMCPServer: MCP server that wraps tool results with token optimization
3
+ */
4
+ export declare class ToonifyMCPServer {
5
+ private server;
6
+ private optimizer;
7
+ private metrics;
8
+ constructor();
9
+ private setupHandlers;
10
+ start(): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=mcp-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../../src/server/mcp-server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,OAAO,CAAmB;;IAqBlC,OAAO,CAAC,aAAa;IA0Ff,KAAK;CAMZ"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * ToonifyMCPServer: MCP server that wraps tool results with token optimization
3
+ */
4
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
5
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
6
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
7
+ import { TokenOptimizer } from '../optimizer/token-optimizer.js';
8
+ import { MetricsCollector } from '../metrics/metrics-collector.js';
9
+ export class ToonifyMCPServer {
10
+ server;
11
+ optimizer;
12
+ metrics;
13
+ constructor() {
14
+ this.server = new Server({
15
+ name: 'claude-code-toonify',
16
+ version: '0.1.0',
17
+ }, {
18
+ capabilities: {
19
+ tools: {},
20
+ },
21
+ });
22
+ this.optimizer = new TokenOptimizer();
23
+ this.metrics = new MetricsCollector();
24
+ this.setupHandlers();
25
+ }
26
+ setupHandlers() {
27
+ // List available tools
28
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
29
+ tools: [
30
+ {
31
+ name: 'optimize_content',
32
+ description: 'Optimize structured data content for token efficiency using TOON format',
33
+ inputSchema: {
34
+ type: 'object',
35
+ properties: {
36
+ content: {
37
+ type: 'string',
38
+ description: 'The content to optimize (JSON, CSV, or YAML)',
39
+ },
40
+ toolName: {
41
+ type: 'string',
42
+ description: 'Name of the tool that generated this content',
43
+ },
44
+ },
45
+ required: ['content'],
46
+ },
47
+ },
48
+ {
49
+ name: 'get_stats',
50
+ description: 'Get token optimization statistics',
51
+ inputSchema: {
52
+ type: 'object',
53
+ properties: {},
54
+ },
55
+ },
56
+ ],
57
+ }));
58
+ // Handle tool calls
59
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
60
+ const { name, arguments: args } = request.params;
61
+ switch (name) {
62
+ case 'optimize_content': {
63
+ const { content, toolName } = args;
64
+ const result = await this.optimizer.optimize(content, {
65
+ toolName: toolName || 'unknown',
66
+ size: content.length,
67
+ });
68
+ // Record metrics
69
+ await this.metrics.record({
70
+ timestamp: new Date().toISOString(),
71
+ toolName: toolName || 'unknown',
72
+ originalTokens: result.originalTokens,
73
+ optimizedTokens: result.optimizedTokens || result.originalTokens,
74
+ savings: result.savings?.tokens || 0,
75
+ savingsPercentage: result.savings?.percentage || 0,
76
+ wasOptimized: result.optimized,
77
+ format: result.format,
78
+ reason: result.reason,
79
+ });
80
+ return {
81
+ content: [
82
+ {
83
+ type: 'text',
84
+ text: JSON.stringify(result, null, 2),
85
+ },
86
+ ],
87
+ };
88
+ }
89
+ case 'get_stats': {
90
+ const stats = await this.metrics.getStats();
91
+ return {
92
+ content: [
93
+ {
94
+ type: 'text',
95
+ text: JSON.stringify(stats, null, 2),
96
+ },
97
+ ],
98
+ };
99
+ }
100
+ default:
101
+ throw new Error(`Unknown tool: ${name}`);
102
+ }
103
+ });
104
+ }
105
+ async start() {
106
+ const transport = new StdioServerTransport();
107
+ await this.server.connect(transport);
108
+ console.error('Toonify MCP Server running on stdio');
109
+ }
110
+ }
111
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../src/server/mcp-server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEnE,MAAM,OAAO,gBAAgB;IACnB,MAAM,CAAS;IACf,SAAS,CAAiB;IAC1B,OAAO,CAAmB;IAElC;QACE,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CACtB;YACE,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,OAAO;SACjB,EACD;YACE,YAAY,EAAE;gBACZ,KAAK,EAAE,EAAE;aACV;SACF,CACF,CAAC;QAEF,IAAI,CAAC,SAAS,GAAG,IAAI,cAAc,EAAE,CAAC;QACtC,IAAI,CAAC,OAAO,GAAG,IAAI,gBAAgB,EAAE,CAAC;QAEtC,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAEO,aAAa;QACnB,uBAAuB;QACvB,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACjE,KAAK,EAAE;gBACL;oBACE,IAAI,EAAE,kBAAkB;oBACxB,WAAW,EAAE,yEAAyE;oBACtF,WAAW,EAAE;wBACX,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE;4BACV,OAAO,EAAE;gCACP,IAAI,EAAE,QAAQ;gCACd,WAAW,EAAE,8CAA8C;6BAC5D;4BACD,QAAQ,EAAE;gCACR,IAAI,EAAE,QAAQ;gCACd,WAAW,EAAE,8CAA8C;6BAC5D;yBACF;wBACD,QAAQ,EAAE,CAAC,SAAS,CAAC;qBACtB;iBACF;gBACD;oBACE,IAAI,EAAE,WAAW;oBACjB,WAAW,EAAE,mCAAmC;oBAChD,WAAW,EAAE;wBACX,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE,EAAE;qBACf;iBACF;aACF;SACF,CAAC,CAAC,CAAC;QAEJ,oBAAoB;QACpB,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACrE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;YAEjD,QAAQ,IAAI,EAAE,CAAC;gBACb,KAAK,kBAAkB,CAAC,CAAC,CAAC;oBACxB,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAG7B,CAAC;oBAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE;wBACpD,QAAQ,EAAE,QAAQ,IAAI,SAAS;wBAC/B,IAAI,EAAE,OAAO,CAAC,MAAM;qBACrB,CAAC,CAAC;oBAEH,iBAAiB;oBACjB,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;wBACxB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;wBACnC,QAAQ,EAAE,QAAQ,IAAI,SAAS;wBAC/B,cAAc,EAAE,MAAM,CAAC,cAAc;wBACrC,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,cAAc;wBAChE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;wBACpC,iBAAiB,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,IAAI,CAAC;wBAClD,YAAY,EAAE,MAAM,CAAC,SAAS;wBAC9B,MAAM,EAAE,MAAM,CAAC,MAAM;wBACrB,MAAM,EAAE,MAAM,CAAC,MAAM;qBACtB,CAAC,CAAC;oBAEH,OAAO;wBACL,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;6BACtC;yBACF;qBACF,CAAC;gBACJ,CAAC;gBAED,KAAK,WAAW,CAAC,CAAC,CAAC;oBACjB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;oBAC5C,OAAO;wBACL,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;6BACrC;yBACF;qBACF,CAAC;gBACJ,CAAC;gBAED;oBACE,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAErC,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACvD,CAAC;CACF"}