@qeekai/ide-client
v0.1.0
Published
Qeek IDE integration client library + Claude Desktop MCP server (QEEK-87 Phase 2).
Downloads
167
Readme
@qeekai/ide-client
Client library + MCP server for the qeek IDE Integration.
Two consumers:
- MCP-aware IDEs — Claude Code, Claude Desktop, Cursor, VS Code
(1.95+). Run
npx @qeekai/ide-clientas an MCP server; the IDE picks up five tools (list-specs,get-spec,ask-spec-question,check-spec-answer,get-repo-context). - Custom IDE extensions — import the lib and wire
IdeApiClientIdeNotificationListenerinto your extension surface (~30 lines).
A user-facing setup + usage guide lives at
docs/ide-integration-user-guide.md
— read that if you just want to use the integration from your IDE.
The rest of this README is for library / extension authors and
people deploying the MCP server.
Quick start — Claude Code
claude mcp add qeek \
--env QEEK_IDE_TOKEN=<qek_live_...> \
--env QEEK_IDE_ACCOUNT=<account-id> \
--env QEEK_IDE_CHAT_SESSION=<chat-session-id> \
-- npx -y @qeekai/ide-clientThe five MCP tools become available in every Claude Code session after the next reload.
Quick start — Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json
(on macOS — Windows/Linux paths in Anthropic's docs):
{
"mcpServers": {
"qeek": {
"command": "npx",
"args": ["-y", "@qeekai/ide-client"],
"env": {
"QEEK_IDE_TOKEN": "<qek_live_...>",
"QEEK_IDE_ACCOUNT": "<your-account-id>",
"QEEK_IDE_CHAT_SESSION": "<chat-session-id-for-clarifications>"
}
}
}
}Restart Claude Desktop. Ask it "What qeek specs do I have?" — it
should call list-specs and reply with your specs.
Getting the three values
QEEK_IDE_TOKEN— long-lived qeek API token, generated from qeek-ui at/settings/api-tokens. Treat as a password; revoke from the same page if leaked.QEEK_IDE_ACCOUNT— your account ID, visible in qeek-ui URLs (https://qeek.ai/account/<id>/…).QEEK_IDE_CHAT_SESSION— the chat session id where clarification answers should land (…/chat/<sessionId>). Optional — if unset, theask-spec-questiontool requireschatSessionIdin the call args.
Quick start — Cursor
Edit ~/.cursor/mcp.json (global) or .cursor/mcp.json in your
project root (per-workspace, takes precedence):
{
"mcpServers": {
"qeek": {
"command": "npx",
"args": ["-y", "@qeekai/ide-client"],
"env": {
"QEEK_IDE_TOKEN": "<qek_live_...>",
"QEEK_IDE_ACCOUNT": "<accountId>",
"QEEK_IDE_CHAT_SESSION": "<chat-session-id>"
}
}
}
}Reload Cursor (Cmd+Shift+P → "Reload Window"). The qeek server
should show up under MCP tools in the agent panel.
Quick start — VS Code
Native MCP support since 1.95. Per-workspace config (preferred — keeps
tokens out of global settings): .vscode/mcp.json in your project root:
{
"servers": {
"qeek": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@qeekai/ide-client"],
"env": {
"QEEK_IDE_TOKEN": "<qek_live_...>",
"QEEK_IDE_ACCOUNT": "<accountId>",
"QEEK_IDE_CHAT_SESSION": "<chat-session-id>"
}
}
}
}Or global: Cmd+Shift+P → "MCP: Add server" → fill in the same
command / args / env. Stored in User Settings.
Custom IDE extensions (advanced)
import {
IdeApiClient,
IdeNotificationListener,
} from "@qeekai/ide-client";
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth, signInWithCustomToken } from "firebase/auth";
const app = initializeApp({ /* your Firebase config */ });
const auth = getAuth(app);
const db = getFirestore(app);
// 1. Sign in (your extension handles this however — paste, OAuth,
// PAT exchange via api_tokens).
await signInWithCustomToken(auth, "<custom-token-from-your-flow>");
// 2. REST client
const api = new IdeApiClient({
baseUrl: "https://qeek-ide-service-bg2lz2topa-uc.a.run.app",
token: () => auth.currentUser!.getIdToken(),
accountId: "<account-id>",
toolType: "vscode",
toolVersion: "0.1.0",
});
const { specs } = await api.listSpecs();
// 3. Notification listener (Firestore push)
const listener = new IdeNotificationListener({
db,
userId: auth.currentUser!.uid,
accountId: "<account-id>",
handlers: {
onSpecUpdated: (notif, payload) => {
vscode.window.showInformationMessage(
`Spec "${payload.specTitle}" updated to v${payload.newVersion}`,
"Refresh",
);
},
onClarificationAnswered: (notif, payload) => {
vscode.window.showInformationMessage(
`qeek answered: ${payload.answer.slice(0, 80)}…`,
);
},
},
});
listener.start();
// Cleanup on extension deactivation
context.subscriptions.push({ dispose: () => listener.stop() });MCP tools
| Tool | What |
|---|---|
| list-specs | List specs in the user's account. Filters: projectId, status, limit. |
| get-spec | Fetch one spec's full content by id. Optional saveTo: true writes to .qeek/specs/<id>.md, or pass a string path (cwd-relative, path-traversal guarded). When set, the assistant can re-read the file across later turns without another API call. |
| ask-spec-question | Submit a clarification question. The qeek agent answers; the answer threads into the user's qeek chat session. The tool long-polls up to 45s for the answer and returns it inline; on timeout returns a questionId for check-spec-answer. |
| check-spec-answer | Poll an in-flight question for its answer. Used when ask-spec-question timed out. |
| get-repo-context | Fetch spec-scoped repo context — per-file summaries, dependency edges, and (when present) project architecture overview + directory structure. Optional saveTo writes a directory of markdown + json files (.qeek/context/<specId>/) the assistant can re-read across turns. Args: depth (minimal | related), includeWiki, repoName, forceRefresh. |
ask-spec-question routes through the existing qeek chat agent (same
model, same cost line). The conversation persists in the user's qeek
chat session, so it shows up in qeek-ui for anyone else looking at
that chat.
Auth model
qeek API tokens (qek_live_…) are long-lived, generated by users
via the qeek-ui /settings/api-tokens page, and the only auth path
the MCP server expects. Revoking from the settings page locks out
subsequent requests on the next call.
IdeApiClient.config.token accepts either a string or a getter
function — the getter is called before every request, so an IDE
extension can plumb a refresh loop in without touching this package.
Configuration
| Env var | Purpose | Default |
|---|---|---|
| QEEK_IDE_TOKEN | qeek API token (Bearer) — qek_live_… | required |
| QEEK_IDE_ACCOUNT | Account ID | required |
| QEEK_IDE_URL | ide-service base URL | prod URL |
| QEEK_IDE_CHAT_SESSION | Default chat session id for ask-spec-question | optional — if unset, tool call must pass chatSessionId |
Development
# Build (from repo root or this package)
pnpm -C ide-client build
# Test
pnpm -C ide-client test
# Run the MCP server locally with stdio (for poking via @modelcontextprotocol/inspector)
QEEK_IDE_TOKEN=... QEEK_IDE_ACCOUNT=... pnpm -C ide-client start:mcpBehaviour notes
get-spectool results are ephemeral. The MCP tool returns the spec as a JSON tool-result block; the assistant reads it for the current turn, but the IDE's context window may compact it away on later turns. UsesaveTo(see the table above) when you want the spec available to re-read across turns / sessions.- No streaming responses. MCP tool calls are request-response; long answers come back as a single text block when the agent finishes generating.
- Notification listener is for IDE extensions, not the MCP server.
MCP prefers synchronous tool responses, so the MCP server uses the
REST polling endpoint (
/v1/ide/questions/:id) instead of opening a Firestore listener. TheIdeNotificationListenerexport is for the VS Code / Cursor extension surface.
Architecture
MCP-aware IDE (Claude Code / Desktop / Cursor / VS Code 1.95+)
│ (stdio MCP protocol)
▼
┌─────────────────────────────────────────┐
│ npx @qeekai/ide-client (this package) │
│ ┌───────────────────────────────────┐ │
│ │ createMcpServer (5 tools) │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ IdeApiClient (REST wrapper) │ │
│ └───────────────────────────────────┘ │
└─────────────────────────────────────────┘
│ HTTPS + Bearer token
▼
┌─────────────────────────────────────────┐
│ ide-service (Cloud Run) │
└─────────────────────────────────────────┘IDE extensions skip the MCP server and use IdeApiClient +
IdeNotificationListener directly.
See also
- User-facing setup + usage:
docs/ide-integration-user-guide.md - Backend HTTP API:
ide-service/README.md - Notification fan-out trigger:
functions/src/ide/specUpdateTrigger.ts - Clarification dispatcher:
functions/src/ide/clarificationDispatcher.ts
