Local Orchestration Router (LOR) is a local MCP server that acts as a catalog, prompt, and workspace-readiness layer for Codex skills and reusable subagent prompt profiles. It lets a configured workspace register known entries, store routing metadata, find relevant catalog entries for a task, generate manual Codex prompts, and improve registered skill context over time.
The current implementation is a Deno TypeScript MCP server that runs as a local
Streamable HTTP server for Codex, with stdio kept as a compatibility and
development fallback. Product specs, use cases, and technical decisions remain
documented under docs/.
LOR is implemented as a runnable local 2.0.0 MCP server.
- Runtime: Deno TypeScript.
- Primary transport: local Streamable HTTP at
http://127.0.0.1:8765/mcp. - Fallback transport: stdio through
deno task run. - Storage: server-owned local SQLite database under
.lor-mcp/by default. - Catalog scope: caller-supplied
workspace, resolved through canonical workspace paths and registered aliases. - Tool surface: type-specific skill and subagent tools, plus catalog import/export, workspace sync, diagnostics, prompt generation, and workspace memory. Public registered-agent catalog tools have been removed from the V2 surface.
- Local context: diagnostics report
AGENTS.mdstatus and local Codex skill alignment without rewriting local instruction files. - Usage analytics: local aggregate counters show which skills, subagents, and workspace notes are listed, matched, and opened in detail without storing raw prompts or note bodies.
- Negative routing metadata: skills and subagents can carry structured "do not use when" guidance so matching can suppress or demote false positives.
- Implementation guidance: selected skills can carry detail-loaded operational guidance without adding large blocks to list or match responses.
Run the local HTTP MCP server:
deno task serveTo load local settings from .env, run:
deno task --env-file=.env serveThen connect Codex to the already-running server:
codex mcp add lor-mcp --url http://127.0.0.1:8765/mcpEquivalent Codex config:
[mcp_servers.lor-mcp]
url = "http://127.0.0.1:8765/mcp"Server-owned storage defaults are used when no environment variables are set:
- SQLite database:
.lor-mcp/catalog.db. - Skill roots:
.temp/skills,~/.codex/skills, and~/.agents/skills.
Catalog tools require a workspace input supplied by the client. LOR normalizes
path-shaped workspace values and resolves registered aliases before reading or
writing catalog rows. For example, /Users/me/project, /Users/me/project/,
and a registered project alias can point at the same canonical workspace. Use
register_workspace_alias when a folder name or older slug should resolve to a
canonical workspace path.
Optional server-side environment overrides:
LOR_DB_PATH: local SQLite database path.LOR_SKILL_ROOTS: comma-separated local skill roots for approvedSKILL.mdsync. LOR resolvesskillName/SKILL.mdunder these roots and does not accept arbitrary skill file paths through MCP tool input.LOR_HOST: local HTTP host, default127.0.0.1.LOR_PORT: local HTTP port, default8765.LOR_LOG_LEVEL: log level, defaultinfo.LOR_LOG_FORMAT: log format, defaultpretty; setjsonfor structured machine-readable logs.
Logs are written to stderr so the stdio MCP fallback can keep stdout reserved for protocol messages. Useful local logging commands:
LOR_LOG_LEVEL=debug deno task serve
LOR_LOG_FORMAT=json deno task serve
deno task --env-file=.env serve
deno task serve 2>&1 | tee /tmp/lor-mcp.logRun the stdio fallback:
deno task runVerification:
deno task check
deno task test
deno task lint
deno task fmtThe configured SQLite driver uses a native library through Deno FFI and may download/cache that library on first use.
Copy this into your Codex personalization or custom instructions so LOR is used consistently across prompts:
When working in a repository, use LOR MCP before substantive planning,
implementation, or review.
Use the current repository path as the LOR workspace. Start by calling
get_workspace_diagnostics and check_catalog_health for that workspace. If the
workspace resolves unexpectedly, use the reported diagnostics to fix or explain
the workspace/alias issue before relying on catalog results.
For routing and context, prefer LOR skills and subagent profiles:
- Use find_matching_skill for relevant registered skill metadata.
- Use find_matching_subagent for reusable scoped prompt profiles.
- Use get_skill_detail or get_subagent_detail when a match needs full metadata.
- Use generate_agent_prompt only when preparing a fresh short-lived Codex chat.
LOR prepares context and prompts; it does not create Codex chats, send messages,
or control other agents. Use native Codex behavior for any chat creation or
handoff, and report clearly when LOR is unavailable or has no useful match.
Keep edits scoped to the user's request, preserve unrelated user work, prefer
existing project patterns, and report exact verification commands and results.
Use LOR as a local routing, prompt, and workspace-knowledge layer for Codex.
Every catalog, prompt, and memory call should include the caller's workspace
so LOR can resolve aliases and keep data isolated by project.
Before meaningful work, ask the active Codex agent to inspect the workspace and route through LOR:
Use LOR MCP with workspace `<workspace>`.
First call get_workspace_diagnostics and check_catalog_health.
Then use find_matching_skill and find_matching_subagent for the current task.
Use get_workspace_diagnostics when a workspace path, folder-name alias, or
older slug may be resolving to the wrong catalog, or when you need to compare
local Codex skills with LOR-registered skill metadata. Use
check_catalog_health to inspect stored verification metadata and
skill/subagent coverage.
Use routing when deciding what context should shape a task:
find_matching_skillfor relevant stored skill metadata.find_matching_subagentfor scoped reusable prompt profiles.get_skill_detailorget_subagent_detailwhen the match result needs full metadata.generate_agent_promptwhen a fresh short-lived Codex task prompt is useful.
Use list_skills and list_subagents when browsing by entry family.
get_skill_detail returns full implementation guidance when a selected skill
has it. get_subagent_detail returns the rendered prompt for a subagent
profile.
propose_skill_updateto preview better stored skill context.apply_skill_updatewithconfirm: trueafter review.preview_skill_file_syncwhen the approved context should be written into the local skill file.apply_skill_file_syncwithconfirm: trueafter reviewing the rendered managed section.
Use promote_skill_to_global when a workspace skill should become available to
other workspaces. New skill registrations default to global scope unless
scope: "workspace" is supplied. Global skills are included in list and match
by default.
Use workspace memory for small coordination notes that are not routing metadata:
remember_workspace_notefor branch plans, review summaries, migration notes, or reapply instructions.list_workspace_notesto scan note summaries, optionally by tag.find_matching_workspace_noteto retrieve ranked note previews for the current task or question.get_workspace_noteto retrieve the full note body.remove_workspace_notewhen the note is obsolete.
Workspace notes are not catalog entries and are not used by skill/subagent
matching. Use find_matching_workspace_note when you want note-specific memory
retrieval.
Use get_usage_analytics to see which skills, subagents, and workspace notes
are actually being listed, matched, or opened in detail. Filter by entryType,
scope, entryKey, or projectName when reviewing a specific family or entry.
Use maintenance and expansion tools when the workspace catalog needs cleanup, backup, or migration:
list_skills,list_subagentsupdate_skill,update_subagentremove_skill,remove_subagentclear_workspace_skills,clear_workspace_subagentsexport_catalogimport_catalogpreview_workspace_catalog_syncapply_workspace_catalog_syncintroduce_subagentget_usage_analytics
flowchart RL
catalog["CATALOG"]
skills["SKILLS"]
subagents["SUBAGENTS"]
catalog --> skills
catalog --> subagents
generatePrompt["generate_agent_prompt"] --> skills
generatePrompt --> subagents
introduceSkill["introduce_skill"] --> skills
promoteSkill["promote_skill_to_global"] --> skills
proposeSkillUpdate["propose_skill_update"] --> applySkillUpdate["apply_skill_update"]
applySkillUpdate --> skills
applySkillUpdate --> previewSkillFileSync["preview_skill_file_sync"]
previewSkillFileSync --> applySkillFileSync["apply_skill_file_sync"]
applySkillFileSync --> skills
introduceSubagent["introduce_subagent"] --> subagents
registerAlias["register_workspace_alias"] --> catalog
catalog --> checkHealth["check_catalog_health"]
catalog --> workspaceDiagnostics["get_workspace_diagnostics"]
catalog --> usageAnalytics["get_usage_analytics"]
catalog --> rememberWorkspaceNote["remember_workspace_note"]
rememberWorkspaceNote --> listWorkspaceNotes["list_workspace_notes"]
listWorkspaceNotes --> findWorkspaceNote["find_matching_workspace_note"]
findWorkspaceNote --> getWorkspaceNote["get_workspace_note"]
getWorkspaceNote --> removeWorkspaceNote["remove_workspace_note"]
catalog --> exportCatalog["export_catalog"]
exportCatalog --> importCatalog["import_catalog"]
catalog --> previewWorkspaceSync["preview_workspace_catalog_sync"]
previewWorkspaceSync --> applyWorkspaceSync["apply_workspace_catalog_sync"]
applyWorkspaceSync --> catalog
skills --> listSkills["list_skills"]
subagents --> listSubagents["list_subagents"]
listSkills --> updateSkill["update_skill"]
updateSkill --> skills
listSubagents --> updateSubagent["update_subagent"]
updateSubagent --> subagents
listSkills --> removeSkill["remove_skill"]
listSubagents --> removeSubagent["remove_subagent"]
removeSkill --> clearSkills["clear_workspace_skills"]
removeSubagent --> clearSubagents["clear_workspace_subagents"]
skills --> findSkill["find_matching_skill"]
subagents --> findSubagent["find_matching_subagent"]
findSkill --> getSkill["get_skill_detail"]
findSubagent --> getSubagent["get_subagent_detail"]
getSkill --> skills
getSubagent --> subagents
listSkills --> usageAnalytics
listSubagents --> usageAnalytics
findSkill --> usageAnalytics
findSubagent --> usageAnalytics
getSkill --> usageAnalytics
getSubagent --> usageAnalytics
listWorkspaceNotes --> usageAnalytics
findWorkspaceNote --> usageAnalytics
getWorkspaceNote --> usageAnalytics
- Version:
2.0.0. - Runtime: Deno TypeScript.
- Primary transport: local Streamable HTTP at
http://127.0.0.1:8765/mcp. - Fallback transport: stdio through
deno task run. - Storage: server-owned local SQLite database under
.lor-mcp/by default. - Catalog scope: caller-supplied
workspace, resolved through canonical workspace paths and registered aliases.
- Matching: deterministic local fuzzy scoring with structured explanations, conflict reporting, and registered skill context signals.
- Global skills: shared skills can be introduced or promoted with
scope: "global"and are included in list/match by default. New skill registrations default to global scope unlessscope: "workspace"is supplied. - Subagents: reusable prompt profiles for small, scoped delegation, with
workspace/global scope and ready-to-use prompts returned from introduction,
matching, and detail flows. New subagent registrations default to global scope
unless
scope: "workspace"is supplied. - Negative routing: skills and subagents can store structured exclusion metadata. Strong negative matches are suppressed, moderate negative matches are demoted, and visible demotions include negative evidence in explanations.
- Implementation guidance: skills can store detail-loaded first-inspect lists, implementation rules, common fix patterns, test expectations, verification, and handoff checklists. Matching does not score this guidance.
- Agent prompts:
generate_agent_promptcreates deterministic ready-to-paste prompts for fresh Codex chats without registering or messaging agents.
- Skill improvement: approval-gated stored skill context updates, with optional
approval-gated sync into a LOR-managed
SKILL.mdsection. - Workspace memory: LOR stores small workspace-scoped notes for durable coordination context outside the routing catalog. Notes are always workspace-scoped and do not accept global scope.
- Workspace diagnostics: LOR can report resolved workspace aliases, catalog counts, and sanitized storage/runtime status without exposing catalog entries.
- HTTP discovery logging: expected OAuth/OIDC
.well-knowndiscovery probe404responses stay below warning severity while real unrelated4xxresponses remain warnings.
CHANGELOG.md: version history.VERSION: current project version.docs/readme.md: planning docs overview.docs/roadmap.md: feature spec roadmap and implementation status.AGENTS.md: repository-specific Codex operating instructions..temp/: local agent-supporting guidance and vendored skills used while developing this repository.