์‹œ๋ฆฌ์ฆˆ: oh-my-claudecode ๋‚ด๋ถ€ ๊ตฌ์กฐ๋ถ€ํ„ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ๊นŒ์ง€

์ด ์‹œ๋ฆฌ์ฆˆ๋Š” Claude Code ํ”Œ๋Ÿฌ๊ทธ์ธ ์‹œ์Šคํ…œ์˜ ๋‚ด๋ถ€ ๋™์ž‘์„ ๋‹จ๊ณ„๋ณ„๋กœ ํ•ด๋ถ€ํ•˜๊ณ , ์ตœ์ข…์ ์œผ๋กœ ๋‚˜๋งŒ์˜ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ง์ ‘ ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒƒ๊นŒ์ง€ ๋„๋‹ฌํ•˜๋Š” ๊ณผ์ •์ด๋‹ค.

ํŽธ๋‚ด์šฉํ•ต์‹ฌ
1ํŽธPlugin Anatomyplugin.json ํ•˜๋‚˜๋กœ ์‹œ์ž‘ํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ผˆ๋Œ€
2ํŽธHook System์ด๋ฒคํŠธ โ†’ stdin JSON โ†’ ์Šคํฌ๋ฆฝํŠธ โ†’ stdout JSON
3ํŽธSkill SystemSKILL.md๋กœ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•
4ํŽธAgent SystemTask tool๋กœ ์œ„์ž„๋˜๋Š” ์‹ค์ œ ์ž‘์—… ์ˆ˜ํ–‰์ž
5ํŽธ (๋ณธ๋ฌธ)MCP Tools BridgeLSP, AST ๋“ฑ ์ปค์Šคํ…€ ๋„๊ตฌ ์„œ๋ฒ„
6ํŽธState & Lifecycle.omc/ ์ƒํƒœ ๊ด€๋ฆฌ์™€ ๋ชจ๋“œ ์ง€์†
7ํŽธParallel OrchestrationUltrawork, Team, Autopilot, Ralph ํŒจํ„ด

  • MCP Tools Bridge๋Š” Claude Code์˜ ๊ธฐ๋ณธ ๋„๊ตฌ๋กœ ๋ถˆ๊ฐ€๋Šฅํ•œ ์ž‘์—…์„ ํ•ด๊ฒฐํ•˜๋Š” ์ปค์Šคํ…€ ๋„๊ตฌ ์„œ๋ฒ„ ์‹œ์Šคํ…œ
  • TypeScript ์†Œ์Šค๋ฅผ esbuild๋กœ ๋ฒˆ๋“ค๋งํ•ด bridge/mcp-server.cjs๋กœ ๋งŒ๋“ค๊ณ , .mcp.json์— ์„œ๋ฒ„ ์ด๋ฆ„ "t"๋กœ ๋“ฑ๋กํ•˜์—ฌ ๋ชจ๋“  ๋„๊ตฌ๋ฅผ mcp__t__๋„๊ตฌ์ด๋ฆ„์œผ๋กœ ๋…ธ์ถœํ•˜๋Š” 2์ค‘ ์„œ๋ฒ„ ์•„ํ‚คํ…์ฒ˜
  • LSP(IDE ๊ธฐ๋Šฅ 12๊ฐœ), AST(๊ตฌ์กฐ ๊ฒ€์ƒ‰ 2๊ฐœ), State(์ƒํƒœ 5๊ฐœ), Notepad(๋ฉ”๋ชจ 6๊ฐœ), Memory(์ง€์‹ 4๊ฐœ), Shared Memory(๊ณต์œ  5๊ฐœ), Skills(3๊ฐœ), Trace(3๊ฐœ), Python REPL(1๊ฐœ) ๋“ฑ ์ด 41๊ฐœ ์ด์ƒ์˜ ์ „๋ฌธ ๋„๊ตฌ๋ฅผ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„๋กœ ๊ด€๋ฆฌํ•˜๋Š” ํ™•์žฅ ํ—ˆ๋ธŒ

ํ•ด๋‹น ๊ฐœ๋…์ด ํ•„์š”ํ•œ ์ด์œ 

  • 4ํŽธ(Agent System)์—์„œ ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—… ์ค‘ ํƒ€์ž… ์ฒดํฌ, ์ฝ”๋“œ ๊ตฌ์กฐ ๊ฒ€์ƒ‰, ์ƒํƒœ ์ €์žฅ, ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ๊นŒ์ง€ ํ•™์Šต
  • Claude Code์˜ ๊ธฐ๋ณธ ๋„๊ตฌ(Read, Write, Bash)๋งŒ์œผ๋กœ๋Š” โ€œ์ด ํŒŒ์ผ์˜ ํƒ€์ž… ์—๋Ÿฌ๊ฐ€ ๋ญ์ง€?โ€, โ€œ์ด ์‹ฌ๋ณผ์˜ ์ •์˜๋Š” ์–ด๋””์ง€?โ€ ๊ฐ™์€ ์งˆ๋ฌธ์— ํšจ์œจ์ ์œผ๋กœ ๋‹ตํ•  ์ˆ˜ ์—†์Œ
  • MCP Server๊ฐ€ IDE๊ธ‰ ๊ธฐ๋Šฅ์„ ๋„๊ตฌ๋กœ ๋…ธ์ถœํ•˜์—ฌ ์—์ด์ „ํŠธ๊ฐ€ ์ •๋ฐ€ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“œ๋Š” ํ•ต์‹ฌ ์ธํ”„๋ผ

AS-IS

sequenceDiagram
    autonumber
    participant AG as Agent
    participant CC as Claude Code
    participant FS as File System

    AG->>CC: Bash("tsc --noEmit 2>&1")
    CC->>FS: tsc ํ”„๋กœ์„ธ์Šค ์‹คํ–‰
    FS-->>CC: ์›์‹œ ํ…์ŠคํŠธ ์ถœ๋ ฅ (์ˆ˜๋ฐฑ ์ค„)
    CC-->>AG: ํŒŒ์‹ฑ ๋ถˆ๊ฐ€๋Šฅํ•œ ํ…์ŠคํŠธ ๋ฉ์–ด๋ฆฌ
    Note over AG: ์—๋Ÿฌ ์œ„์น˜ยท์‹ฌ๊ฐ๋„ ํŒŒ์‹ฑ์„<br/>LLM์ด ์ง์ ‘ ํ•ด์•ผ ํ•จ

TO-BE

sequenceDiagram
    autonumber
    participant AG as Agent
    participant CC as Claude Code
    participant MCP as MCP Server "t"
    participant LSP as lsp-tools.ts

    AG->>CC: mcp__t__lsp_diagnostics({ file: "src/main.ts" })
    CC->>MCP: JSON-RPC ์š”์ฒญ
    MCP->>LSP: lsp_diagnostics ํ•ธ๋“ค๋Ÿฌ
    LSP->>LSP: Language Server ํ”„๋กœํ† ์ฝœ ํ˜ธ์ถœ
    LSP-->>MCP: ๊ตฌ์กฐํ™”๋œ ์—๋Ÿฌ ๋ชฉ๋ก (ํŒŒ์ผ, ์ค„, ์‹ฌ๊ฐ๋„)
    MCP-->>CC: JSON-RPC ์‘๋‹ต
    CC-->>AG: ์ฆ‰์‹œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํƒ€์ž… ์—๋Ÿฌ ์ •๋ณด
    Note over AG: ํŒŒ์‹ฑ ๋ถˆํ•„์š”,<br/>๋ฐ”๋กœ ์ˆ˜์ • ์ž‘์—… ์‹œ์ž‘

2์ค‘ ์„œ๋ฒ„ ์•„ํ‚คํ…์ฒ˜

OMC๋Š” ๋™์ผ ๊ณ„์—ด์˜ ๋„๊ตฌ๋ฅผ ๋‘ ๊ฐ€์ง€ ๊ฒฝ๋กœ๋กœ ์ œ๊ณตํ•˜๋˜, ํฌํ•จ ๋ฒ”์œ„๊ฐ€ ๋‹ค๋ฅด๋‹ค.

graph TD
    subgraph "Pattern A: Standalone (ํ”Œ๋Ÿฌ๊ทธ์ธ ๋กœ๋“œ ์‹œ)"
        MJ[".mcp.json<br/>์„œ๋ฒ„ ์ด๋ฆ„: t"] -->|"node bridge/mcp-server.cjs"| SS["standalone-server.ts<br/>(raw MCP SDK)"]
        SS -->|"StdioServerTransport"| CC1["Claude Code"]
    end

    subgraph "Pattern B: In-process (์„œ๋ธŒ์—์ด์ „ํŠธ์šฉ)"
        OTS["omc-tools-server.ts<br/>(Claude Agent SDK)"] -->|"createSdkMcpServer()"| SA["์„œ๋ธŒ์—์ด์ „ํŠธ"]
    end

    SS -->|"zodToJsonSchema() ์ˆ˜๋™ ๋ณ€ํ™˜"| TOOLS_A["7์นดํ…Œ๊ณ ๋ฆฌ 33๊ฐœ ๋„๊ตฌ"]
    OTS -->|"tool() ํ—ฌํผ ์ž๋™ ๋ณ€ํ™˜"| TOOLS_B["10์นดํ…Œ๊ณ ๋ฆฌ 41+ ๋„๊ตฌ"]
๊ตฌ๋ถ„Pattern A (Standalone)Pattern B (In-process)
์ง„์ž…์ bridge/mcp-server.cjssrc/mcp/omc-tools-server.ts
SDK@modelcontextprotocol/sdk (Server ํด๋ž˜์Šค)Claude Agent SDK
์Šคํ‚ค๋งˆ ๋ณ€ํ™˜zodToJsonSchema() ์ˆ˜๋™ ๊ตฌํ˜„tool() ํ—ฌํผ๊ฐ€ ์ž๋™ ์ฒ˜๋ฆฌ
ํ†ต์‹ StdioServerTransport (ํ”„๋กœ์„ธ์Šค ๊ฐ„)์ธ๋ฉ”๋ชจ๋ฆฌ (๊ฐ™์€ ํ”„๋กœ์„ธ์Šค)
๋„๊ตฌ ๋ฒ”์œ„LSP, AST, Python, State, Notepad, Memory, Trace (33๊ฐœ)์ขŒ์ธก ์ „๋ถ€ + Skills, Shared Memory, Interop (41+๊ฐœ)
๋น„ํ™œ์„ฑํ™”์ง€์› ์•ˆ ํ•จparseDisabledGroups()๋กœ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ๋น„ํ™œ์„ฑํ™”
์šฉ๋„Claude Code๊ฐ€ ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ์ง์ ‘ ์‚ฌ์šฉ์„œ๋ธŒ์—์ด์ „ํŠธ์˜ allowedTools์— ํฌํ•จ

Pattern A์—์„œ Claude Code๋Š” .mcp.json์„ ์ฝ๊ณ  node bridge/mcp-server.cjs๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. ์ด ํ”„๋กœ์„ธ์Šค๋Š” StdioServerTransport๋ฅผ ํ†ตํ•ด JSON-RPC ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ ๋ฐ›์œผ๋ฉฐ, Claude Code ์ž…์žฅ์—์„œ ๋ชจ๋“  ๋„๊ตฌ๊ฐ€ mcp__t__๋„๊ตฌ์ด๋ฆ„์œผ๋กœ ๋…ธ์ถœ๋œ๋‹ค.

๋„๊ตฌ ๋“ฑ๋ก ํŒจํ„ด: tagCategory + parseDisabledGroups

๋“ฑ๋ก ํ๋ฆ„

graph LR
    subgraph "1. ๋„๊ตฌ ์ •์˜"
        L["lsp-tools.ts"] --> TC["tagCategory(lspTools, 'lsp')"]
        A["ast-tools.ts"] --> TC2["tagCategory(astTools, 'ast')"]
        S["state-tools.ts"] --> TC3["tagCategory(stateTools, 'state')"]
        N["notepad-tools.ts"] --> TC4["...๋‚˜๋จธ์ง€ ์นดํ…Œ๊ณ ๋ฆฌ"]
    end

    subgraph "2. ๋น„ํ™œ์„ฑํ™” ํ•„ํ„ฐ"
        ENV["OMC_DISABLE_TOOLS=lsp,python-repl"] --> PD["parseDisabledGroups()"]
        PD --> FILTER["allTools.filter(t => !disabled.has(t.category))"]
    end

    TC --> AT["allTools ๋ฐฐ์—ด"]
    TC2 --> AT
    TC3 --> AT
    TC4 --> AT
    AT --> FILTER
    FILTER --> SDK["enabledTools โ†’ createSdkMcpServer()"]

๋น„ํ™œ์„ฑํ™” ๋งคํ•‘

OMC_DISABLE_TOOLS=lsp,python-repl,project-memory
ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๊ฐ’๋น„ํ™œ์„ฑํ™” ์นดํ…Œ๊ณ ๋ฆฌ
lspLSP 12๊ฐœ ๋„๊ตฌ ์ „์ฒด
astAST 2๊ฐœ ๋„๊ตฌ
python ๋˜๋Š” python-replPython REPL 1๊ฐœ
stateState 5๊ฐœ ๋„๊ตฌ
notepadNotepad 6๊ฐœ ๋„๊ตฌ
memory ๋˜๋Š” project-memoryMemory 4๊ฐœ ๋„๊ตฌ
skillsSkills 3๊ฐœ ๋„๊ตฌ
traceTrace 3๊ฐœ ๋„๊ตฌ
shared-memoryShared Memory 5๊ฐœ ๋„๊ตฌ
interopInterop ๋„๊ตฌ (์กฐ๊ฑด๋ถ€)

ํŒŒ์‹ฑ์€ ์„œ๋ฒ„ ์‹œ์ž‘ ์‹œ 1ํšŒ๋งŒ ์ˆ˜ํ–‰. ๋Ÿฐํƒ€์ž„ ์ค‘ ๋™์  ํ™œ์„ฑํ™”/๋น„ํ™œ์„ฑํ™”๋Š” ๋ถˆ๊ฐ€ํ•˜๋ฉฐ ์„œ๋ฒ„ ์žฌ์‹œ์ž‘ ํ•„์š”.

์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ๋„๊ตฌ ์ƒ์„ธ

LSP Tools (12๊ฐœ) โ€” IDE๊ธ‰ ์ฝ”๋“œ ๋ถ„์„

LSP (Language Server Protocol)์„ ํ†ตํ•ด ์‹ค์ œ ์–ธ์–ด ์„œ๋ฒ„(TypeScript, Python ๋“ฑ)์— ์งˆ์˜ํ•˜์—ฌ ์ •ํ™•ํ•œ ํƒ€์ž… ์ •๋ณด์™€ ์ฝ”๋“œ ๋ถ„์„ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋ชจ๋“  LSP ๋„๊ตฌ๋Š” withLspClient(filePath, operationName, fn) ํ—ฌํผ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค:

  1. ํŒŒ์ผ ํ™•์žฅ์ž๋กœ ์ ํ•ฉํ•œ Language Server ํƒ์ƒ‰
  2. lspClientManager.runWithClientLease()๋กœ LSP ํด๋ผ์ด์–ธํŠธ ํš๋“/์ƒ์„ฑ
  3. ์„œ๋ฒ„ ๋ฏธ์„ค์น˜ ์‹œ ์„ค์น˜ ์•ˆ๋‚ด์™€ ํ•จ๊ป˜ ์—๋Ÿฌ ๋ฐ˜ํ™˜
๋„๊ตฌํŒŒ๋ผ๋ฏธํ„ฐ์—ญํ• 
lsp_hoverfile, line, character์‹ฌ๋ณผ์˜ ํƒ€์ž… ์ •๋ณด/๋ฌธ์„œ ๋ฐ˜ํ™˜
lsp_goto_definitionfile, line, character์‹ฌ๋ณผ ์ •์˜ ์œ„์น˜ (ํŒŒ์ผ ๊ฒฝ๋กœ + ์ค„)
lsp_find_referencesfile, line, character, includeDeclaration?์‹ฌ๋ณผ์ด ์‚ฌ์šฉ๋œ ๋ชจ๋“  ์œ„์น˜
lsp_document_symbolsfileํŒŒ์ผ ๋‚ด ์‹ฌ๋ณผ ๊ณ„์ธต ๋ชฉ๋ก
lsp_workspace_symbolsquery, file์›Œํฌ์ŠคํŽ˜์ด์Šค ์ „์ฒด ์‹ฌ๋ณผ ๊ฒ€์ƒ‰
lsp_diagnosticsfile, severity?ํŒŒ์ผ ๋‹จ์œ„ ์—๋Ÿฌ/๊ฒฝ๊ณ  ๋ชฉ๋ก
lsp_diagnostics_directorydirectory, strategy?ํ”„๋กœ์ ํŠธ ๋‹จ์œ„ ์ง„๋‹จ (tsc/lsp/auto)
lsp_servers(์—†์Œ)์„ค์น˜๋œ Language Server ์ƒํƒœ
lsp_prepare_renamefile, line, character๋ฆฌ๋„ค์ž„ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ํ™•์ธ
lsp_renamefile, line, character, newName๋ฆฌ๋„ค์ž„ ๋ฏธ๋ฆฌ๋ณด๊ธฐ (์ ์šฉํ•˜์ง€ ์•Š์Œ)
lsp_code_actionsfile, startLine, startChar, endLine, endChar๋ฆฌํŒฉํ† ๋ง ์ œ์•ˆ ๋ชฉ๋ก
lsp_code_action_resolve์œ„ + actionIndexํŠน์ • ์•ก์…˜์˜ ํŽธ์ง‘ ์ƒ์„ธ

AST Tools (2๊ฐœ) โ€” ๊ตฌ์กฐ์  ์ฝ”๋“œ ๊ฒ€์ƒ‰/๋ณ€ํ™˜

@ast-grep/napi ๋„ค์ดํ‹ฐ๋ธŒ ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•œ๋‹ค. ์ •๊ทœ์‹ ๊ธฐ๋ฐ˜ ๊ฒ€์ƒ‰๊ณผ ๋‹ฌ๋ฆฌ AST ํŒจํ„ด ๋งค์นญ์œผ๋กœ ๊ตฌ๋ฌธ ๊ตฌ์กฐ๋ฅผ ์ •ํ™•ํžˆ ํŒŒ์•…ํ•œ๋‹ค.

๋„๊ตฌํŒŒ๋ผ๋ฏธํ„ฐ์—ญํ• 
ast_grep_searchpattern, language, path?, context?(0-10์ค„), maxResults?(1-100)AST ํŒจํ„ด ์ฝ”๋“œ ๊ฒ€์ƒ‰
ast_grep_replacepattern, replacement, language, path?, dryRun?(๊ธฐ๋ณธ true)AST ํŒจํ„ด ์ฝ”๋“œ ๋ณ€ํ™˜

ํŒจํ„ด ๋ฌธ๋ฒ•: $NAME(๋‹จ์ผ ๋…ธ๋“œ), $$$ARGS(๋‹ค์ค‘ ๋…ธ๋“œ) ์˜ˆ์‹œ: console.log($MSG) โ†’ ๋ชจ๋“  console.log ํ˜ธ์ถœ ๋งค์นญ

์ง€์› ์–ธ์–ด: javascript, typescript, tsx, python, ruby, go, rust, java, kotlin, swift, c, cpp, csharp, html, css, json, yaml

State Tools (5๊ฐœ) โ€” ๋ชจ๋“œ ์ƒํƒœ ๊ด€๋ฆฌ

.omc/state/ ๋””๋ ‰ํ† ๋ฆฌ์— JSON ํŒŒ์ผ๋กœ ๋ชจ๋“œ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. session_id ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์„ธ์…˜๋ณ„ ๊ฒฉ๋ฆฌ๋ฅผ ์ง€์›ํ•˜๋ฉฐ, ๋ฏธ์ง€์ • ์‹œ ๋ ˆ๊ฑฐ์‹œ ๊ณต์œ  ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค(๊ต์ฐจ ์˜ค์—ผ ๊ฒฝ๊ณ  ๋ฐœ์ƒ).

์ง€์› ๋ชจ๋“œ: autopilot, team, ralph, ultrawork, ultraqa, ralplan, omc-teams, deep-interview

๋„๊ตฌํ•ต์‹ฌ ๋™์ž‘
state_read๋ชจ๋“œ ์ƒํƒœ JSON ์ฝ๊ธฐ
state_write์ƒํƒœ ๊ธฐ๋ก (atomicWriteJsonSync ์‚ฌ์šฉ, _meta ์ž๋™ ์ถ”๊ฐ€)
state_clear์ƒํƒœ ์‚ญ์ œ (team ๋ชจ๋“œ๋Š” ๋Ÿฐํƒ€์ž„ ์ƒํƒœ + HUD๋„ ์ •๋ฆฌ)
state_list_activeํ˜„์žฌ ํ™œ์„ฑ ๋ชจ๋“œ ๋ชฉ๋ก
state_get_statusํŠน์ • ๋ชจ๋“œ์˜ ์ƒ์„ธ ์ƒํƒœ

state_write๋Š” atomicWriteJsonSync()๋กœ ์›์ž์  ์“ฐ๊ธฐ๋ฅผ ๋ณด์žฅํ•˜์—ฌ ๋™์‹œ ์ ‘๊ทผ ์‹œ ๋ถ€๋ถ„ ์“ฐ๊ธฐ๋ฅผ ๋ฐฉ์ง€ํ•œ๋‹ค.

Notepad Tools (6๊ฐœ) โ€” ์„ธ์…˜ ๊ฐ„ ๊ตฌ์กฐํ™” ๋ฉ”๋ชจ๋ฆฌ

.omc/notepad.md์— 3๊ฐœ ์„น์…˜์œผ๋กœ ๊ตฌ๋ถ„๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.

๋„๊ตฌ์„น์…˜ํŠน์„ฑ
notepad_write_priorityPriority Context๊ต์ฒด(REPLACE) ๋ฐฉ์‹, ํ•ญ์ƒ ์„ธ์…˜ ์‹œ์ž‘ ์‹œ ๋กœ๋“œ, 500์ž ์ด๋‚ด ๊ถŒ์žฅ
notepad_write_workingWorking Memory์ถ”๊ฐ€(APPEND) ๋ฐฉ์‹, ํƒ€์ž„์Šคํƒฌํ”„ ํฌํ•จ, 7์ผ ํ›„ ์ž๋™ ์ •๋ฆฌ
notepad_write_manualManual์ถ”๊ฐ€ ๋ฐฉ์‹, ์ž๋™ ์ •๋ฆฌ ์—†์Œ
notepad_read์„ ํƒ ๊ฐ€๋Šฅall/priority/working/manual ์ค‘ ํƒ
notepad_pruneWorking Memory์˜ค๋ž˜๋œ ํ•ญ๋ชฉ ์ •๋ฆฌ (๊ธฐ๋ณธ 7์ผ)
notepad_stats์ „์ฒดํฌ๊ธฐ, ํ•ญ๋ชฉ ์ˆ˜, ์ตœ๊ณ ๋ น ํ•ญ๋ชฉ, ๊ฒฝ๋กœ

Memory Tools (4๊ฐœ) โ€” ํ”„๋กœ์ ํŠธ ์ง€์‹ ์ €์žฅ์†Œ

.omc/project-memory.json์— ๊ตฌ์กฐํ™”๋œ ํ”„๋กœ์ ํŠธ ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.

์„น์…˜: techStack, build, conventions, structure, customNotes, userDirectives

๋„๊ตฌ์—ญํ• 
project_memory_readํ”„๋กœ์ ํŠธ ํ™˜๊ฒฝ ์ •๋ณด ์ฝ๊ธฐ (์„น์…˜ ์„ ํƒ ๊ฐ€๋Šฅ)
project_memory_writeํ”„๋กœ์ ํŠธ ์ง€์‹ ๊ธฐ๋ก (merge ๋ชจ๋“œ ์ง€์›)
project_memory_add_note์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์ปค์Šคํ…€ ๋…ธํŠธ ์ถ”๊ฐ€
project_memory_add_directive์‚ฌ์šฉ์ž ์ง€์‹œ์‚ฌํ•ญ ์ถ”๊ฐ€ (์ปจํ…์ŠคํŠธ ์••์ถ•์—์„œ ์‚ด์•„๋‚จ์Œ)

Shared Memory Tools (5๊ฐœ) โ€” ์—์ด์ „ํŠธ ๊ฐ„ ๊ณต์œ  ์ €์žฅ์†Œ

.omc/state/shared-memory/{namespace}/{key}.json์— ํ‚ค-๋ฐธ๋ฅ˜ ํ˜•ํƒœ๋กœ ์—์ด์ „ํŠธ ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•œ๋‹ค. ~/.claude/.omc-config.json์˜ agents.sharedMemory.enabled๋กœ ๊ฒŒ์ดํŠธ๋จ.

๋„๊ตฌ์—ญํ• 
shared_memory_writeํ‚ค-๋ฐธ๋ฅ˜ ์ €์žฅ (TTL ์ง€์›, ์ตœ๋Œ€ 7์ผ)
shared_memory_readํ‚ค-๋ฐธ๋ฅ˜ ์ฝ๊ธฐ (๋งŒ๋ฃŒ ์ž๋™ ๊ฐ์ง€)
shared_memory_list๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋‚ด ํ‚ค ๋ชฉ๋ก ๋˜๋Š” ์ „์ฒด ๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋ชฉ๋ก
shared_memory_deleteํ‚ค ์‚ญ์ œ
shared_memory_cleanup๋งŒ๋ฃŒ๋œ ํ•ญ๋ชฉ ์ผ๊ด„ ์ •๋ฆฌ

๋‚˜๋จธ์ง€ ๋„๊ตฌ

์นดํ…Œ๊ณ ๋ฆฌ๋„๊ตฌ ์ˆ˜์—ญํ• 
Skills Tools3๊ฐœ.omc/skills/(ํ”„๋กœ์ ํŠธ) + ~/.omc/skills/(๊ธ€๋กœ๋ฒŒ) ์Šคํ‚ฌ ํƒ์ƒ‰ยท๋ชฉ๋ก
Trace Tools3๊ฐœ.omc/state/agent-replay-*.jsonl ์„ธ์…˜ ๋ฆฌํ”Œ๋ ˆ์ด ํƒ€์ž„๋ผ์ธยท์š”์•ฝยท๊ฒ€์ƒ‰
Python REPL1๊ฐœPython ์ฝ”๋“œ ์‹คํ–‰

Bridge ๋นŒ๋“œ ํŒŒ์ดํ”„๋ผ์ธ

๋นŒ๋“œ ํ๋ฆ„

graph TD
    subgraph "TypeScript ์†Œ์Šค"
        S1["src/mcp/standalone-server.ts"]
        S2["src/mcp/omc-tools-server.ts"]
        S3["src/team/bridge-entry.ts"]
    end

    subgraph "๋นŒ๋“œ ์Šคํฌ๋ฆฝํŠธ"
        B1["scripts/build-mcp-server.mjs"]
        B2["scripts/build-bridge-entry.mjs"]
        B3["scripts/build-skill-bridge.mjs"]
    end

    subgraph "bridge/ ์‚ฐ์ถœ๋ฌผ"
        O1["mcp-server.cjs<br/>~25,000์ค„ CJS ๋ฒˆ๋“ค"]
        O2["team-bridge.cjs"]
        O3["skill-bridge ๊ด€๋ จ"]
    end

    S1 -->|"esbuild"| B1 --> O1
    S3 -->|"esbuild"| B2 --> O2
    B3 --> O3

    style S2 fill:#ffd,stroke:#aa0
    S2 -.->|"๋ฒˆ๋“ค๋ง ์•ˆ ๋จ<br/>(In-process ์ „์šฉ)"| SA["์„œ๋ธŒ์—์ด์ „ํŠธ์—์„œ<br/>์ง์ ‘ import"]

esbuild ์„ค์ • ํ•ต์‹ฌ

esbuild.build({
  entryPoints: ['src/mcp/standalone-server.ts'],
  bundle: true,
  platform: 'node',
  target: 'node18',
  format: 'cjs',
  outfile: 'bridge/mcp-server.cjs',
  external: [
    'fs', 'path', 'os', /* ...Node.js ๋นŒํŠธ์ธ */
    '@ast-grep/napi',    // ๋„ค์ดํ‹ฐ๋ธŒ ์• ๋“œ์˜จ โ†’ ๋ฒˆ๋“ค ๋ถˆ๊ฐ€
    'better-sqlite3'     // ๋„ค์ดํ‹ฐ๋ธŒ ์• ๋“œ์˜จ โ†’ ๋ฒˆ๋“ค ๋ถˆ๊ฐ€
  ],
  banner: { js: '<NODE_PATH ํ•ด์„๊ธฐ ํ”„๋ฆฌ์•ฐ๋ธ”>' }
});

NODE_PATH ํ”„๋ฆฌ์•ฐ๋ธ”

bridge/mcp-server.cjs ์ตœ์ƒ๋‹จ์— ์‚ฝ์ž…๋˜๋Š” ์ฝ”๋“œ:

try {
  var _globalRoot = require('child_process')
    .execSync('npm root -g', { encoding: 'utf8' }).trim();
  process.env.NODE_PATH = _globalRoot + ':' + process.env.NODE_PATH;
  require('module')._initPaths();
} catch (_e) { /* graceful degrade */ }

์™ธ๋ถ€ํ™”๋œ @ast-grep/napi, better-sqlite3 ๊ฐ™์€ ๋„ค์ดํ‹ฐ๋ธŒ ๋ชจ๋“ˆ์„ ๋Ÿฐํƒ€์ž„์— ๊ธ€๋กœ๋ฒŒ npm ๊ฒฝ๋กœ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ํŠธ๋ฆญ์ด๋‹ค.

Graceful Shutdown

process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
process.on('SIGINT', () => gracefulShutdown('SIGINT'));

์ข…๋ฃŒ ์‹œ disconnectAll()์„ ํ˜ธ์ถœํ•œ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ lspClientManager.disconnectAll()์„ ์‹คํ–‰ํ•˜์—ฌ LSP ์ž์‹ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ •๋ฆฌํ•˜๊ณ  ๊ณ ์•„ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ฐฉ์ง€ํ•œ๋‹ค.

๋‚˜๋งŒ์˜ MCP ๋„๊ตฌ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค๋ฉด

// src/tools/my-tools.ts
import { z } from 'zod';
 
export const myTools = [
  {
    name: 'my_custom_tool',
    description: 'My custom tool description',
    schema: z.object({ input: z.string() }),
    handler: async (args: { input: string }) => ({
      content: [{ type: 'text' as const, text: `Result: ${args.input}` }]
    })
  }
];
// omc-tools-server.ts์— ๋“ฑ๋ก
const allTools = [
  ...tagCategory(myTools, 'my-category'),
  // ...๊ธฐ์กด ๋„๊ตฌ๋“ค
];

npm run build ํ›„ mcp__t__my_custom_tool๋กœ ํ˜ธ์ถœ ๊ฐ€๋Šฅ.

์ฐธ๊ณ  ๋ฌธ์„œ