@goonnguyen/human-mcp 1.2.0 → 1.3.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/.claude/agents/project-manager.md +2 -2
- package/.env.example +28 -1
- package/.github/workflows/publish.yml +43 -6
- package/.opencode/agent/code-reviewer.md +142 -0
- package/.opencode/agent/debugger.md +74 -0
- package/.opencode/agent/docs-manager.md +119 -0
- package/.opencode/agent/git-manager.md +60 -0
- package/.opencode/agent/planner-researcher.md +100 -0
- package/.opencode/agent/project-manager.md +113 -0
- package/.opencode/agent/system-architecture.md +200 -0
- package/.opencode/agent/tester.md +96 -0
- package/.opencode/agent/ui-ux-developer.md +97 -0
- package/.opencode/command/cook.md +7 -0
- package/.opencode/command/debug.md +10 -0
- package/.opencode/command/fix/ci.md +8 -0
- package/.opencode/command/fix/fast.md +5 -0
- package/.opencode/command/fix/hard.md +7 -0
- package/.opencode/command/fix/test.md +16 -0
- package/.opencode/command/git/cm.md +5 -0
- package/.opencode/command/git/cp.md +4 -0
- package/.opencode/command/plan/ci.md +12 -0
- package/.opencode/command/plan/two.md +13 -0
- package/.opencode/command/plan.md +10 -0
- package/.opencode/command/test.md +7 -0
- package/.opencode/command/watzup.md +8 -0
- package/CHANGELOG.md +21 -0
- package/CLAUDE.md +5 -3
- package/QUICKSTART.md +3 -3
- package/README.md +551 -20
- package/bun.lock +275 -3
- package/dist/index.js +71091 -17256
- package/docs/README.md +51 -0
- package/docs/codebase-structure-architecture-code-standards.md +17 -5
- package/docs/project-overview-pdr.md +37 -21
- package/docs/project-roadmap.md +494 -0
- package/human-mcp.png +0 -0
- package/package.json +9 -1
- package/plans/002-sse-fallback-http-transport-plan.md +161 -0
- package/plans/003-fix-test-infrastructure-and-ci-plan.md +699 -0
- package/plans/003-http-transport-local-file-access-plan.md +880 -0
- package/plans/004-fix-typescript-compilation-errors-plan.md +388 -0
- package/plans/005-comprehensive-test-infrastructure-fix-plan.md +854 -0
- package/src/index.ts +2 -0
- package/src/tools/eyes/index.ts +7 -7
- package/src/tools/eyes/processors/image.ts +90 -0
- package/src/transports/http/file-interceptor.ts +134 -0
- package/src/transports/http/routes.ts +165 -4
- package/src/transports/http/server.ts +64 -14
- package/src/transports/http/session.ts +11 -3
- package/src/transports/http/sse-routes.ts +210 -0
- package/src/transports/index.ts +11 -6
- package/src/transports/types.ts +13 -0
- package/src/utils/cloudflare-r2.ts +107 -0
- package/src/utils/config.ts +26 -0
- package/tests/integration/http-transport-files.test.ts +190 -0
- package/tests/integration/server.test.ts +4 -1
- package/tests/integration/sse-transport.test.ts +142 -0
- package/tests/setup.ts +45 -1
- package/tests/types/api-responses.ts +35 -0
- package/tests/types/test-types.ts +105 -0
- package/tests/unit/cloudflare-r2.test.ts +118 -0
- package/tests/unit/eyes-analyze.test.ts +150 -0
- package/tests/unit/formatters.test.ts +1 -1
- package/tests/unit/sse-routes.test.ts +92 -0
- package/tests/utils/error-scenarios.ts +198 -0
- package/tests/utils/index.ts +3 -0
- package/tests/utils/mock-helpers.ts +99 -0
- package/tests/utils/test-data-generators.ts +217 -0
- package/tests/utils/test-server-manager.ts +172 -0
- package/tsconfig.json +1 -1
- package/plans/reports/001-from-qa-engineer-to-development-team-test-suite-report.md +0 -188
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { startHttpTransport } from "../../src/transports/http/server.js";
|
|
3
|
+
import type { HttpTransportConfig, HttpServerHandle } from "../../src/transports/types.js";
|
|
4
|
+
|
|
5
|
+
export class TestServerManager {
|
|
6
|
+
private servers: Map<number, HttpServerHandle> = new Map();
|
|
7
|
+
private usedPorts: Set<number> = new Set();
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Get a random available port for testing using OS-level port checking
|
|
11
|
+
*/
|
|
12
|
+
async getAvailablePort(): Promise<number> {
|
|
13
|
+
// Try sequential ports starting from a random high port
|
|
14
|
+
const basePort = 4000 + Math.floor(Math.random() * 1000);
|
|
15
|
+
const maxAttempts = 50;
|
|
16
|
+
|
|
17
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
18
|
+
const port = basePort + attempt;
|
|
19
|
+
|
|
20
|
+
if (!this.usedPorts.has(port) && await this.isPortAvailable(port)) {
|
|
21
|
+
this.usedPorts.add(port);
|
|
22
|
+
return port;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
throw new Error(`Unable to find available port after ${maxAttempts} attempts (tried ${basePort} to ${basePort + maxAttempts - 1})`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Check if a port is available using Node.js net module
|
|
31
|
+
*/
|
|
32
|
+
private async isPortAvailable(port: number): Promise<boolean> {
|
|
33
|
+
return new Promise((resolve) => {
|
|
34
|
+
const net = require('net');
|
|
35
|
+
const server = net.createServer();
|
|
36
|
+
|
|
37
|
+
server.listen(port, '127.0.0.1', () => {
|
|
38
|
+
server.close(() => {
|
|
39
|
+
resolve(true);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
server.on('error', () => {
|
|
44
|
+
resolve(false);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Start a test server with the given configuration
|
|
51
|
+
*/
|
|
52
|
+
async startTestServer(config: Partial<HttpTransportConfig> = {}): Promise<{
|
|
53
|
+
server: HttpServerHandle;
|
|
54
|
+
port: number;
|
|
55
|
+
baseUrl: string;
|
|
56
|
+
}> {
|
|
57
|
+
const port = await this.getAvailablePort();
|
|
58
|
+
|
|
59
|
+
// Create a basic MCP server for testing
|
|
60
|
+
const mcpServer = new McpServer(
|
|
61
|
+
{
|
|
62
|
+
name: "test-server",
|
|
63
|
+
version: "1.0.0"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
capabilities: {
|
|
67
|
+
tools: {}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const serverConfig: HttpTransportConfig = {
|
|
73
|
+
port,
|
|
74
|
+
host: "127.0.0.1",
|
|
75
|
+
sessionMode: "stateful",
|
|
76
|
+
enableSse: true,
|
|
77
|
+
enableJsonResponse: true,
|
|
78
|
+
enableSseFallback: true,
|
|
79
|
+
ssePaths: {
|
|
80
|
+
stream: "/sse",
|
|
81
|
+
message: "/messages"
|
|
82
|
+
},
|
|
83
|
+
security: {
|
|
84
|
+
enableCors: true,
|
|
85
|
+
enableDnsRebindingProtection: true,
|
|
86
|
+
allowedHosts: ["127.0.0.1", "localhost"]
|
|
87
|
+
},
|
|
88
|
+
...config
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const server = await startHttpTransport(mcpServer, serverConfig);
|
|
92
|
+
this.servers.set(port, server);
|
|
93
|
+
|
|
94
|
+
// Wait for server to be ready
|
|
95
|
+
await this.waitForServerReady(port);
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
server,
|
|
99
|
+
port,
|
|
100
|
+
baseUrl: `http://127.0.0.1:${port}`
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Wait for server to be ready by checking health endpoint
|
|
106
|
+
*/
|
|
107
|
+
private async waitForServerReady(port: number, timeout = 15000): Promise<void> {
|
|
108
|
+
const startTime = Date.now();
|
|
109
|
+
let lastError: Error | undefined;
|
|
110
|
+
|
|
111
|
+
while (Date.now() - startTime < timeout) {
|
|
112
|
+
try {
|
|
113
|
+
const response = await fetch(`http://127.0.0.1:${port}/health`, {
|
|
114
|
+
signal: AbortSignal.timeout(2000)
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
if (response.ok) {
|
|
118
|
+
const health = await response.json() as { status: string };
|
|
119
|
+
if (health.status === 'healthy') {
|
|
120
|
+
// Give the server a bit more time to fully initialize
|
|
121
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} catch (error) {
|
|
126
|
+
lastError = error as Error;
|
|
127
|
+
// Server not ready yet, continue waiting
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
await new Promise(resolve => setTimeout(resolve, 250));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
throw new Error(`Server on port ${port} did not become ready within ${timeout}ms. Last error: ${lastError?.message || 'Unknown'}`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Stop a specific server by port
|
|
138
|
+
*/
|
|
139
|
+
async stopServer(port: number): Promise<void> {
|
|
140
|
+
const server = this.servers.get(port);
|
|
141
|
+
if (server) {
|
|
142
|
+
await server.close();
|
|
143
|
+
this.servers.delete(port);
|
|
144
|
+
this.usedPorts.delete(port);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Stop all test servers
|
|
150
|
+
*/
|
|
151
|
+
async stopAllServers(): Promise<void> {
|
|
152
|
+
const stopPromises = Array.from(this.servers.keys()).map(port => this.stopServer(port));
|
|
153
|
+
await Promise.all(stopPromises);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Get the number of active servers
|
|
158
|
+
*/
|
|
159
|
+
getActiveServerCount(): number {
|
|
160
|
+
return this.servers.size;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Check if any servers are still running
|
|
165
|
+
*/
|
|
166
|
+
hasActiveServers(): boolean {
|
|
167
|
+
return this.servers.size > 0;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Global test server manager instance
|
|
172
|
+
export const testServerManager = new TestServerManager();
|
package/tsconfig.json
CHANGED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
# Human MCP Test Suite Analysis Report
|
|
2
|
-
|
|
3
|
-
**Report Generated:** September 8, 2025
|
|
4
|
-
**Project:** Human MCP - Model Context Protocol Server
|
|
5
|
-
**Test Framework:** Bun Test
|
|
6
|
-
**Report By:** QA Engineer
|
|
7
|
-
|
|
8
|
-
## Executive Summary
|
|
9
|
-
|
|
10
|
-
The test suite execution reveals **3 failing tests out of 10 total tests** (70% pass rate). While TypeScript compilation passes successfully, there are critical inconsistencies between test expectations and actual implementation that need immediate attention.
|
|
11
|
-
|
|
12
|
-
## Test Results Overview
|
|
13
|
-
|
|
14
|
-
- **Total Tests:** 10
|
|
15
|
-
- **Tests Passed:** 7 (70%)
|
|
16
|
-
- **Tests Failed:** 3 (30%)
|
|
17
|
-
- **Tests Skipped:** 0
|
|
18
|
-
- **Execution Time:** 417ms
|
|
19
|
-
- **TypeScript Compilation:** ✅ PASS
|
|
20
|
-
|
|
21
|
-
## Detailed Test Failures
|
|
22
|
-
|
|
23
|
-
### 1. Formatters Test Failure: Accessibility Prompt
|
|
24
|
-
|
|
25
|
-
**File:** `tests/unit/formatters.test.ts`
|
|
26
|
-
**Test:** "should create accessibility prompt"
|
|
27
|
-
**Status:** ❌ FAIL
|
|
28
|
-
|
|
29
|
-
**Issue:** Test expects "concise analysis" text in accessibility prompt for basic detail level, but the actual implementation uses "Provide a concise analysis focusing on the most important findings." instead.
|
|
30
|
-
|
|
31
|
-
**Expected:** `"concise analysis"`
|
|
32
|
-
**Received:** Full prompt text without the expected substring
|
|
33
|
-
|
|
34
|
-
**Root Cause:** Mismatch between test expectations and the `createPrompt()` function implementation in `src/tools/eyes/utils/formatters.ts`.
|
|
35
|
-
|
|
36
|
-
### 2. Config Test Failure: Default Model Mismatch
|
|
37
|
-
|
|
38
|
-
**File:** `tests/unit/config.test.ts`
|
|
39
|
-
**Test:** "should override defaults with environment variables"
|
|
40
|
-
**Status:** ❌ FAIL
|
|
41
|
-
|
|
42
|
-
**Issue:** Test expects `"gemini-2.0-flash-exp"` model but actual implementation returns `"gemini-2.5-flash"`.
|
|
43
|
-
|
|
44
|
-
**Expected:** `"gemini-2.0-flash-exp"`
|
|
45
|
-
**Received:** `"gemini-2.5-flash"`
|
|
46
|
-
|
|
47
|
-
**Root Cause:** The test is setting `process.env.GOOGLE_GEMINI_MODEL = "gemini-2.5-flash"` but expecting a different model name in the assertion.
|
|
48
|
-
|
|
49
|
-
### 3. Server Integration Test Failure: Type Mismatch
|
|
50
|
-
|
|
51
|
-
**File:** `tests/integration/server.test.ts`
|
|
52
|
-
**Test:** "should be properly configured"
|
|
53
|
-
**Status:** ❌ FAIL
|
|
54
|
-
|
|
55
|
-
**Issue:** Test expects server to be instance of `Server` class but receives `McpServer` instance.
|
|
56
|
-
|
|
57
|
-
**Expected:** Instance of `Server` (from `@modelcontextprotocol/sdk/server/index.js`)
|
|
58
|
-
**Received:** Instance of `McpServer`
|
|
59
|
-
|
|
60
|
-
**Root Cause:** Incorrect import and type expectation. The `createServer()` function returns `McpServer` instance, not `Server`.
|
|
61
|
-
|
|
62
|
-
## Coverage Analysis
|
|
63
|
-
|
|
64
|
-
**Note:** No coverage metrics are currently configured in the project. The package.json does not include coverage scripts.
|
|
65
|
-
|
|
66
|
-
**Recommendations for Coverage:**
|
|
67
|
-
- Add coverage collection with `bun test --coverage`
|
|
68
|
-
- Target minimum 80% coverage for critical paths
|
|
69
|
-
- Focus on vision analysis tools and configuration validation
|
|
70
|
-
|
|
71
|
-
## Performance Metrics
|
|
72
|
-
|
|
73
|
-
- **Test Execution Time:** 417ms (Acceptable)
|
|
74
|
-
- **Slowest Individual Test:** ~1.54ms (Server creation test)
|
|
75
|
-
- **Average Test Time:** ~41.7ms per test
|
|
76
|
-
|
|
77
|
-
The test performance is excellent with sub-second execution time.
|
|
78
|
-
|
|
79
|
-
## Critical Issues Requiring Immediate Attention
|
|
80
|
-
|
|
81
|
-
### High Priority
|
|
82
|
-
1. **Config Test Logic Error:** Test is setting an environment variable to one value but expecting a different value
|
|
83
|
-
2. **Server Type Mismatch:** Import and expectation mismatch for server type
|
|
84
|
-
|
|
85
|
-
### Medium Priority
|
|
86
|
-
1. **Formatter Test Expectations:** String matching issues in prompt generation tests
|
|
87
|
-
|
|
88
|
-
## Detailed Recommendations
|
|
89
|
-
|
|
90
|
-
### 1. Fix Config Test (HIGH PRIORITY)
|
|
91
|
-
**Location:** `tests/unit/config.test.ts:28`
|
|
92
|
-
|
|
93
|
-
```typescript
|
|
94
|
-
// Current problematic code:
|
|
95
|
-
process.env.GOOGLE_GEMINI_MODEL = "gemini-2.5-flash";
|
|
96
|
-
expect(config.gemini.model).toBe("gemini-2.0-flash-exp"); // Wrong expectation
|
|
97
|
-
|
|
98
|
-
// Should be:
|
|
99
|
-
process.env.GOOGLE_GEMINI_MODEL = "gemini-2.0-flash-exp";
|
|
100
|
-
expect(config.gemini.model).toBe("gemini-2.0-flash-exp");
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### 2. Fix Server Type Test (HIGH PRIORITY)
|
|
104
|
-
**Location:** `tests/integration/server.test.ts:22`
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
// Current problematic code:
|
|
108
|
-
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
109
|
-
expect(server).toBeInstanceOf(Server);
|
|
110
|
-
|
|
111
|
-
// Should be:
|
|
112
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
113
|
-
expect(server).toBeInstanceOf(McpServer);
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### 3. Fix Formatter Test (MEDIUM PRIORITY)
|
|
117
|
-
**Location:** `tests/unit/formatters.test.ts:30`
|
|
118
|
-
|
|
119
|
-
Update test expectation to match actual implementation:
|
|
120
|
-
```typescript
|
|
121
|
-
// Either update the test expectation:
|
|
122
|
-
expect(prompt).toContain("Provide a concise analysis");
|
|
123
|
-
|
|
124
|
-
// Or update the formatters.ts implementation to include "concise analysis"
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### 4. Add Test Coverage (MEDIUM PRIORITY)
|
|
128
|
-
Add to package.json:
|
|
129
|
-
```json
|
|
130
|
-
{
|
|
131
|
-
"scripts": {
|
|
132
|
-
"test:coverage": "bun test --coverage",
|
|
133
|
-
"test:watch": "bun test --watch"
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### 5. Enhance Test Suite (LOW PRIORITY)
|
|
139
|
-
- Add error scenario testing for vision analysis tools
|
|
140
|
-
- Add integration tests for Google Gemini API calls (with mocking)
|
|
141
|
-
- Add performance benchmarks for image/video processing
|
|
142
|
-
- Add end-to-end tests for MCP protocol compliance
|
|
143
|
-
|
|
144
|
-
## Test Quality Assessment
|
|
145
|
-
|
|
146
|
-
### Strengths
|
|
147
|
-
- Good separation between unit and integration tests
|
|
148
|
-
- Proper use of test setup/teardown with `beforeEach`/`afterAll`
|
|
149
|
-
- Environment variable management in tests
|
|
150
|
-
- Structured test organization
|
|
151
|
-
|
|
152
|
-
### Weaknesses
|
|
153
|
-
- Missing error scenario coverage
|
|
154
|
-
- No mocking for external dependencies (Google Gemini API)
|
|
155
|
-
- Limited edge case testing
|
|
156
|
-
- Missing performance validation tests
|
|
157
|
-
|
|
158
|
-
## Security Considerations
|
|
159
|
-
|
|
160
|
-
- Tests properly manage environment variables for API keys
|
|
161
|
-
- No sensitive data leakage detected in test files
|
|
162
|
-
- Test environment isolation appears adequate
|
|
163
|
-
|
|
164
|
-
## Next Steps (Prioritized)
|
|
165
|
-
|
|
166
|
-
1. **IMMEDIATE:** Fix the 3 failing tests by correcting assertions and imports
|
|
167
|
-
2. **SHORT TERM:** Add test coverage collection and reporting
|
|
168
|
-
3. **MEDIUM TERM:** Expand test suite with error scenarios and edge cases
|
|
169
|
-
4. **LONG TERM:** Add performance benchmarks and comprehensive integration tests
|
|
170
|
-
|
|
171
|
-
## Build Process Verification
|
|
172
|
-
|
|
173
|
-
- **TypeScript Compilation:** ✅ PASS - No type errors detected
|
|
174
|
-
- **Dependency Resolution:** ✅ PASS - All imports resolve correctly
|
|
175
|
-
- **Build Configuration:** ✅ PASS - Project builds successfully
|
|
176
|
-
|
|
177
|
-
## Files Requiring Attention
|
|
178
|
-
|
|
179
|
-
1. `/Users/duynguyen/www/human-mcp/tests/unit/config.test.ts` - Fix environment variable test logic
|
|
180
|
-
2. `/Users/duynguyen/www/human-mcp/tests/integration/server.test.ts` - Fix server type expectation
|
|
181
|
-
3. `/Users/duynguyen/www/human-mcp/tests/unit/formatters.test.ts` - Update string expectations
|
|
182
|
-
4. `/Users/duynguyen/www/human-mcp/package.json` - Add coverage scripts
|
|
183
|
-
|
|
184
|
-
---
|
|
185
|
-
|
|
186
|
-
**Quality Gate Status:** ❌ BLOCKED
|
|
187
|
-
**Reason:** 3 failing tests prevent production deployment
|
|
188
|
-
**Required Action:** Fix failing tests before proceeding with any releases
|