coder/agentapi compatible HTTP API server using Claude Agent SDK on AWS Bedrock
npm install @takutakahashi/claude-agentapiA coder/agentapi compatible HTTP API server that uses Claude Agent SDK TypeScript on AWS Bedrock.
This project implements a server compatible with the coder/agentapi specification, allowing you to interact with Claude AI agents through a standardized HTTP API. The server uses the Claude Agent SDK V2 and can be configured to use either AWS Bedrock or the Anthropic API.
- ✅ Full coder/agentapi compatibility
- ✅ Claude Agent SDK V2 integration
- ✅ AWS Bedrock support
- ✅ Anthropic API support (API Key and OAuth Token)
- ✅ Claude Code compatible configuration (.claude/config.json)
- ✅ MCP (Model Context Protocol) servers support
- ✅ Plugin marketplace support
- ✅ Prometheus metrics export (Claude Code compatible)
- ✅ Server-Sent Events (SSE) for real-time updates
- ✅ Multi-turn conversation support
- ✅ AskUserQuestion and ExitPlanMode tool handling
- ✅ TypeScript with strict type checking
- ✅ Problem+JSON error responses
- 📖 /action エンドポイント使用ガイド - エージェントとの対話的なやり取りの詳細な使用方法
- Node.js 20.x or higher
- AWS account with Bedrock access (if using Bedrock)
- Or Anthropic API key or OAuth token (if using Anthropic API)
#### From GitHub Packages
``bashCreate a .env file with your configuration
cat > .env << 'EOF'
PORT=3000
HOST=localhost
CLAUDE_CODE_USE_BEDROCK=0
ANTHROPIC_MODEL=default
ANTHROPIC_OAUTH_TOKEN=your_oauth_token_here
EOF
#### From npm Registry (if published)
`bash
Create a .env file with your configuration
cat > .env << 'EOF'
PORT=3000
HOST=localhost
CLAUDE_CODE_USE_BEDROCK=0
ANTHROPIC_MODEL=default
ANTHROPIC_OAUTH_TOKEN=your_oauth_token_here
EOFRun with npx (npm)
npx claude-agentapiOr with bunx (Bun)
bunx claude-agentapi
`$3
1. Clone the repository:
`bash
git clone
cd claude-agentapi
`2. Install dependencies:
`bash
npm install
`3. Configure environment variables:
`bash
cp .env.example .env
Edit .env with your configuration
`Configuration
This server supports two configuration methods:
1. Claude Code compatible
.claude/config.json - For MCP servers and hooks
2. Environment variables - For server settings and API credentials$3
This server uses the Claude Agent SDK v1 API (
query function) which supports MCP servers, hooks, and other configurations. Configuration files are loaded in the following order (later configs override earlier ones):1. Global:
~/.claude/config.json
2. Project: .claude/config.json (current working directory)
3. Working directory: {CLAUDE_WORKING_DIRECTORY}/.claude/config.jsonSupported Configuration:
- ✅
mcpServers - MCP server configurations (fully supported)
- ✅ hooks - Hook callbacks for responding to events
- ✅ plugins - Loaded from ~/.claude/settings.json enabledPlugins
- Automatically resolves plugin paths from marketplaces
- Supports custom marketplaces via extraKnownMarketplaces
- Example: "code-simplifier@claude-plugins-official": true
- ⏳ commands - Custom command configurations (not yet implemented)#### Example
.claude/config.json`json
{
"mcpServers": {
"example-server": {
"command": "node",
"args": ["/path/to/mcp-server.js"],
"env": {
"API_KEY": "your-api-key"
}
}
}
}
`See
.claude/config.json.example for a complete example with all supported options.#### Configuration Structure
-
mcpServers: MCP (Model Context Protocol) server configurations
- command: Command to execute the MCP server
- args: Array of command-line arguments
- env: Environment variables for the server process
- disabled: Set to true to disable a server without removing its configuration-
plugins / skills: Plugin/skill configurations
- enabled: Whether the plugin is enabled
- config: Plugin-specific configuration object-
hooks: Hook configurations for executing commands at specific events
- command: Command to execute when the hook is triggered
- args: Array of command-line arguments
- env: Environment variables for the hook process
- Common hooks: user-prompt-submit-hook, tool-call-hook-
commands: Custom command definitions
- command: Command to execute
- args: Array of command-line arguments
- env: Environment variables for the command process
- description: Description of what the command does$3
Create a
.env file based on .env.example:#### Server Configuration
-
PORT - Server port (default: 3000)
- HOST - Server host (default: localhost)#### Model Configuration
-
ANTHROPIC_MODEL - Claude model name (default: default)#### AWS Bedrock Configuration (when using Bedrock)
-
CLAUDE_CODE_USE_BEDROCK=1 - Enable Bedrock
- AWS_REGION - AWS region (e.g., us-east-1)
- AWS_ACCESS_KEY_ID - AWS access key
- AWS_SECRET_ACCESS_KEY - AWS secret key
- AWS_SESSION_TOKEN - AWS session token (optional)#### Anthropic API Configuration (when not using Bedrock)
Use either API Key or OAuth Token (not both):
-
ANTHROPIC_API_KEY - Your Anthropic API key
- ANTHROPIC_OAUTH_TOKEN - Your Anthropic OAuth token#### Agent Permission Configuration
-
CLAUDE_WORKING_DIRECTORY - Working directory for the agent (default: current working directory)
- CLAUDE_PERMISSION_MODE - Permission mode: default, acceptEdits, or bypassPermissions (default: default)
- DANGEROUSLY_SKIP_PERMISSIONS - Set to true to skip all permission checks (equivalent to bypassPermissions mode)
- CLAUDE_CODE_EXECUTABLE_PATH - Custom path to Claude Code executable (optional, uses SDK built-in executable by default)Permission Modes:
-
default - Standard permission checks with user prompts for confirmations
- acceptEdits - Automatically approve file edits (still prompts for other operations)
- bypassPermissions - Skip all permission checks (⚠️ use with extreme caution)#### Telemetry Configuration
-
CLAUDE_CODE_ENABLE_TELEMETRY - Enable OpenTelemetry metrics export (set to 1 to enable)
- PROMETHEUS_PORT - Prometheus metrics server port (default: 9464)#### Other Configuration
-
DEBUG - Enable debug logging (default: false)
- MAX_MESSAGE_HISTORY - Maximum messages to keep in history (default: 100)Usage
$3
If you used npx/bunx for installation:
`bash
Make sure you have a .env file in the current directory
npx claude-agentapi
or
bunx claude-agentapi
`$3
`bash
npm run dev
`$3
`bash
npm run build
npm start
`$3
`bash
npm run type-check
`$3
`bash
npm run lint
npm run lint:fix
`$3
The CLI accepts the following command-line options:
####
--dangerously-skip-permissions
Disables all permission checks by setting the permission mode to bypassPermissions. This allows the agent to perform any operation without asking for confirmation.⚠️ WARNING: Use this option with extreme caution! The agent will have unrestricted access to your filesystem and can execute any commands without prompts.
`bash
npx claude-agentapi --dangerously-skip-permissions
`####
--working-directory or -w
Sets the working directory for the agent. This allows the agent to access files relative to the specified directory, including .claude and other configuration directories.`bash
npx claude-agentapi --working-directory /path/to/your/project
or
npx claude-agentapi -w /path/to/your/project
`####
--permission-mode or -p
Sets the permission mode for the agent. Valid options are default, acceptEdits, or bypassPermissions.`bash
npx claude-agentapi --permission-mode acceptEdits
or
npx claude-agentapi -p acceptEdits
`Example with multiple options:
`bash
npx claude-agentapi \
--working-directory /path/to/project \
--permission-mode acceptEdits
`API Endpoints
The server implements the following
coder/agentapi compatible endpoints:$3
Health check endpoint.Response:
`json
{
"status": "ok"
}
`$3
Get current agent status.Response:
`json
{
"agent_type": "claude",
"status": "running" | "stable"
}
`$3
Get conversation message history (user and assistant messages only).Query Parameters:
Pagination options (all optional):
1. Limit and Direction - Get first/last n messages:
-
limit (number): Number of messages to retrieve
- direction (string): head (first n) or tail (last n, default)2. Around a Message - Get messages around a specific message ID:
-
around (number): Message ID to center around
- context (number): Number of messages before/after (default: 10)Examples:
`bash
Get all messages (no pagination)
GET /messagesGet last 10 messages (most recent)
GET /messages?limit=10Get first 5 messages
GET /messages?limit=5&direction=headGet 3 messages before and after message ID 42
GET /messages?around=42&context=3Get 10 messages before and after message ID 100 (default context)
GET /messages?around=100
`Response:
`json
{
"messages": [
{
"id": 1,
"role": "user" | "assistant",
"content": "Message content",
"time": "2024-01-01T00:00:00.000Z",
"type": "normal" | "question" | "plan"
}
],
"total": 100,
"hasMore": true
}
`Response Fields:
-
messages: Array of message objects
- total: Total number of messages available
- hasMore: Whether there are more messages beyond the returned setParameter Validation:
-
limit must be a positive integer
- direction must be either head or tail
- around must be a non-negative integer
- context requires around to be specified
- around cannot be used with limit or direction$3
Get currently active tool executions. When a tool starts executing, it appears in this list. When the tool completes (success or error), it is removed from the list.Response:
`json
{
"messages": [
{
"id": 2,
"role": "agent",
"content": "{\"type\":\"tool_use\",\"name\":\"Read\",\"id\":\"toolu_123\",\"input\":{\"file_path\":\"/path/to/file\"}}",
"time": "2024-01-01T00:00:00.000Z",
"toolUseId": "toolu_123"
}
]
}
`$3
Send a message to the agent.Request:
`json
{
"content": "Your message",
"type": "user" | "raw"
}
`Response:
`json
{
"ok": true
}
`Error (409 - Agent Busy):
`json
{
"type": "about:blank",
"title": "Agent is busy",
"status": 409,
"detail": "The agent is currently processing another request."
}
`$3
Get a list of pending actions that require user response.Response:
`json
{
"pending_actions": [
{
"type": "answer_question",
"tool_use_id": "toolu_123",
"content": {
"questions": [
{
"question": "Which library should we use?",
"header": "Library",
"multiSelect": false,
"options": [
{ "label": "React", "description": "UI library" },
{ "label": "Vue", "description": "Progressive framework" }
]
}
]
}
}
]
}
`$3
Send an action to the agent. Supports multiple action types for different agent interactions.📖 詳細な使用方法については /action エンドポイント使用ガイド を参照してください。
#### Action Type:
answer_question
Answer questions from the AskUserQuestion tool.Request:
`json
{
"type": "answer_question",
"answers": {
"question1": "answer1",
"question2": "answer2"
}
}
`Response:
`json
{
"ok": true
}
`Error (409 - No Active Question):
`json
{
"type": "about:blank",
"title": "No active question",
"status": 409,
"detail": "There is no active question to answer. The agent must be running and waiting for user input."
}
`#### Action Type:
approve_plan
Approve or reject a plan presented by the ExitPlanMode tool.Request (Approve):
`json
{
"type": "approve_plan",
"approved": true
}
`Request (Reject):
`json
{
"type": "approve_plan",
"approved": false
}
`Response:
`json
{
"ok": true
}
`Error (409 - No Active Plan):
`json
{
"type": "about:blank",
"title": "No active plan",
"status": 409,
"detail": "There is no active plan to approve. The agent must be running and waiting for plan approval."
}
`#### Action Type:
stop_agent
Stop the currently running agent.Request:
`json
{
"type": "stop_agent"
}
`Response:
`json
{
"ok": true
}
`Note: This action can be called at any time, regardless of agent status.
$3
Server-Sent Events (SSE) stream for real-time updates.Events:
1.
init - Initial state on connection
`json
{
"messages": [...],
"status": "stable"
}
`2.
message_update - New message
`json
{
"id": "msg_1_1234567890",
"role": "assistant",
"content": "Message content",
"time": "2024-01-01T00:00:00.000Z"
}
`3.
status_change - Agent status changed
`json
{
"status": "running" | "stable"
}
`Architecture
`
src/
├── index.ts # Application entry point
├── server.ts # Express server configuration
├── routes/ # API route handlers
│ ├── status.ts # GET /status
│ ├── messages.ts # GET /messages
│ ├── message.ts # POST /message
│ ├── action.ts # POST /action
│ ├── tool_status.ts # GET /tool_status
│ └── events.ts # GET /events (SSE)
├── services/ # Business logic
│ ├── agent.ts # Claude Agent SDK integration
│ ├── session.ts # SSE session management
│ └── metrics.ts # Prometheus metrics collection
├── types/ # TypeScript type definitions
│ ├── api.ts # API types
│ ├── agent.ts # Agent types
│ └── config.ts # Configuration types
└── utils/ # Utility functions
├── logger.ts # Logging utility
├── sse.ts # SSE helper
├── config.ts # Configuration loader
└── telemetry.ts # OpenTelemetry setup
`MCP Servers and Plugins
$3
This server supports Model Context Protocol (MCP) servers, allowing you to extend Claude's capabilities with custom tools and integrations.
MCP servers are configured in
.claude/config.json under the mcpServers key. Each server configuration includes:- The command to execute
- Optional arguments
- Environment variables
- An optional
disabled flag to temporarily disable a serverExample MCP server configuration:
`json
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/directory"]
},
"database": {
"command": "docker",
"args": ["run", "-i", "my-mcp-db-server"],
"env": {
"DATABASE_URL": "postgresql://localhost/mydb"
}
}
}
}
`$3
Plugins extend Claude's functionality with additional capabilities. Configure plugins in
.claude/config.json under the plugins or skills key.Example plugin configuration:
`json
{
"plugins": {
"code-reviewer": {
"enabled": true,
"config": {
"strictness": "high",
"languages": ["typescript", "python"]
}
}
}
}
`Note: The
skills key is an alias for plugins and works identically.$3
Hooks allow you to execute custom commands when specific events occur during agent operation. Configure hooks in
.claude/config.json under the hooks key.Example hook configuration:
`json
{
"hooks": {
"user-prompt-submit-hook": {
"command": "bash",
"args": ["-c", "echo 'User prompt submitted'"],
"env": {
"HOOK_TYPE": "user-prompt-submit"
}
},
"tool-call-hook": {
"command": "node",
"args": ["/path/to/tool-call-logger.js"]
}
}
}
`Common hook types:
-
user-prompt-submit-hook: Triggered when a user submits a prompt
- tool-call-hook: Triggered when the agent calls a tool
- And more depending on Claude Agent SDK support$3
Define custom commands that can be invoked during agent operation. Configure commands in
.claude/config.json under the commands key.Example command configuration:
`json
{
"commands": {
"deploy": {
"command": "bash",
"args": ["-c", "npm run deploy"],
"description": "Deploy the application to production",
"env": {
"NODE_ENV": "production"
}
},
"test": {
"command": "npm",
"args": ["test"],
"description": "Run the test suite"
}
}
}
`Commands can be invoked by the agent or used for custom workflows within your application.
Prometheus Metrics
This server implements OpenTelemetry metrics export to Prometheus, following Claude Code's metric naming and structure.
$3
Enable metrics collection by setting the following environment variables:
`bash
Enable telemetry
export CLAUDE_CODE_ENABLE_TELEMETRY=1Optional: Set custom Prometheus port (default: 9464)
export PROMETHEUS_PORT=9464
`Once enabled, Prometheus metrics will be available at:
`
http://localhost:9464/metrics
`$3
The following metrics are exported following Claude Code's naming conventions:
| Metric Name | Description | Unit | Attributes |
|-------------|-------------|------|------------|
|
claude_code.session.count | Count of sessions started | count | session.id, app.version, terminal.type |
| claude_code.token.usage | Number of tokens used | tokens | session.id, app.version, terminal.type, model, type (input/output/cacheRead/cacheCreation) |
| claude_code.cost.usage | Cost of the session | USD | session.id, app.version, terminal.type, model |
| claude_code.lines_of_code.count | Lines of code modified | count | session.id, app.version, terminal.type, type (added/removed) |
| claude_code.code_edit_tool.decision | Code editing tool permission decisions | count | session.id, app.version, terminal.type, tool (Edit/Write/NotebookEdit), decision (accept/reject), language |
| claude_code.active_time.total | Total active time | seconds | session.id, app.version, terminal.type |$3
All metrics include the following standard attributes:
-
session.id - Unique session identifier (UUID)
- app.version - Application version from package.json
- terminal.type - Terminal type (from TERM environment variable)$3
Example Prometheus configuration:
`yaml
scrape_configs:
- job_name: 'claude-agentapi'
static_configs:
- targets: ['localhost:9464']
scrape_interval: 60s
`$3
You can visualize these metrics using Grafana. Example queries:
`promql
Total sessions started
sum(claude_code_session_count)Token usage by type
sum by (type) (claude_code_token_usage)Total cost in USD
sum(claude_code_cost_usage)Lines of code added vs removed
sum by (type) (claude_code_lines_of_code_count)
`Special Features
$3
The
/action endpoint provides a unified interface for interacting with the agent through different action types:#### 1. Answer Questions (
answer_question)
When the agent uses the AskUserQuestion tool:
- The server automatically formats and broadcasts the question with type: "question" (❓ emoji prefix)
- Client sends answers via /action with type: "answer_question"
- Answers are sent back to the agent as a tool_resultExample workflow:
1. Agent calls
AskUserQuestion → Server broadcasts question message
2. Client sends: POST /action with {"type": "answer_question", "answers": {"q1": "a1"}}
3. Server forwards answer to agent as tool_result#### 2. Approve/Reject Plans (
approve_plan)
When the agent uses the ExitPlanMode tool:
- The server formats and broadcasts the plan with type: "plan" (📋 emoji prefix)
- Client approves or rejects via /action with type: "approve_plan"
- Approval/rejection is sent back to the agent as a tool_resultExample workflow:
1. Agent calls
ExitPlanMode → Server broadcasts plan message
2. Client sends: POST /action with {"type": "approve_plan", "approved": true}
3. Server forwards approval to agent as tool_result#### 3. Stop Agent (
stop_agent)
Allows interrupting the agent at any time:
- Can be called regardless of agent status
- Immediately interrupts the running query
- Sets agent status to stableExample:
- Client sends:
POST /action with {"type": "stop_agent"}
- Server interrupts agent and returns to stable stateError Handling
The server uses the Problem+JSON format (RFC 7807) for error responses:
`json
{
"type": "about:blank",
"title": "Error title",
"status": 400,
"detail": "Detailed error message"
}
`Limitations
- Single session only (no multi-session support)
- Raw message type (
type: "raw") not yet implemented
- File upload endpoint (POST /upload) not yet implementedDevelopment
$3
The project follows a modular architecture with clear separation of concerns:
- Routes: Handle HTTP requests/responses
- Services: Implement business logic
- Types: Define TypeScript interfaces
- Utils: Provide shared utilities
$3
1. Define types in
src/types/
2. Implement logic in src/services/
3. Create route handlers in src/routes/
4. Register routes in src/server.ts`MIT
- coder/agentapi
- Claude Agent SDK Documentation
- AWS Bedrock Documentation