Skip to main content
Glama
TadMSTR
by TadMSTR

task-queue-mcp

Built with Claude Code License: MIT

에이전트 오케스트레이션 작업 큐를 MCP 도구 인터페이스로 노출하는 FastMCP 서버입니다. 에이전트는 원시 YAML 파일 쓰기 대신 타입이 지정되고 검증된 도구를 통해 작업을 제출하고, 상태를 확인하고, 완료를 기록합니다.

포트 8485에서 Docker 컨테이너로 실행됩니다. ~/.claude.json에 전역으로 연결되어 모든 Claude Code 에이전트 세션이 접근할 수 있습니다.

도구

Tool

Description

submit_task

status: submitted 상태로 새 작업을 생성한다

list_tasks

선택적 필터로 작업을 나열한다; TTL이 만료된 작업은 제외

get_task

UUID로 단일 작업을 조회한다(보관된 작업도 확인한다)

update_task

에이전트 대상 상태 전이(엄격); 기록 항목을 추가한다

set_task_status

운영자 상태 변경 — 승인, 취소, 보류, 또는 놓친 작업 진행(감사된 오버라이드)

cancel_task

오래된 작업을 위한 정상적인 종료 cancelled 상태(기록은 유지되고 절대 삭제되지 않음)

park_task

작업을 숨기지 않고 일시 중지 — 목록에 계속 표시, TTL 면제, 아무도 가져가지 않음

unpark_task

보류된 작업을 보류 전 상태로 되돌린다

amend_task

대기 중인 작업에 수정 사항을 추가한다; 원래 설명은 절대 다시 쓰이지 않는다

에이전트는 엄격한 update_task 경로를 사용합니다. 운영자는(HTTP 제어 API를 통해) set_task_status / cancel_task / park_task / unpark_task를 사용합니다. 에이전트는 취소하거나 보류할 수 없습니다. 둘 다 운영자 전용입니다. amend_task는 예외입니다. 작업의 소스 에이전트는 수정할 수 있지만 대상 에이전트는 수정할 수 없습니다.

submit_task

submit_task(
    source_agent="research",
    target_agent="deploy-agent",  # agent name or "auto" for dispatcher routing
    # build | deploy | fix | research | review | audit | notify | docs |
    # ticket_audit | ticket_audit_complete
    task_type="build",
    summary="Deploy qmd update",
    description="Apply the qmd stack update from build plan...",
    risk_level="low",  # low | medium | high (default: low)
    requires_approval=False,  # explicit override of approval gate
    priority="normal",  # normal | high | urgent (default: normal)
    context_refs=["/srv/agents/build-plans/qmd/plan.md"],  # absolute paths only
    ttl_days=30,
    workflow_mode="semi-auto",  # semi-auto | auto (default: semi-auto)
    originating_task_id=None,  # UUID of the parent task, if this is a return task
)
# → {"ok": true, "task_id": "<uuid>", "filename": "<timestamp>-<slug>.yml"}

context_refs는 절대 경로여야 합니다. risk_levelpriority는 허용 목록에 대해 검증됩니다. workflow_mode는 디스패처 동작을 제어합니다. semi-auto(기본값)는 Matrix 알림과 함께 운영자 픽업을 위해 작업을 대기시키고, auto는 디스패처가 대상 에이전트를 헤드리스로 시작하도록 트리거합니다. 서버는 UUID를 생성하고, created를 설정하고, retry_policy 스텁을 초기화합니다.

원본 작업의 자동 종료(v0.6.0부터)

originating_task_id를 전달하면 부모 작업이 completed로 종료됩니다. 반환 작업을 제출하는 것이 곧 요청을 종료하는 것입니다. 이 기능이 실행되면 응답에 auto_closed_task_id가 추가됩니다.

다음 조건이 모두 충족되어야만 실행됩니다.

조건

이유

부모가 존재하고 보관되지 않음

그렇지 않으면 종료할 대상이 없음

parent.target_agent == source_agent

기능 전체의 경계 조건 — 에이전트 A는 부모로 지목함으로써 에이전트 B의 작업을 종료할 수 없어야 합니다. operator도 허용하는 update_task의 소유권 검사에 의존하지 않고 여기서 명시적으로 확인합니다.

parent.source_agent == target_agent

반환 형태의 나머지 절반 — 요청한 상대에게 답하고 있어야 합니다. 이 조건이 없으면 전달 요청이 반환과 동일해 보입니다(아래 참조).

부모가 approved 또는 in-progress 상태임

parked는 운영자의 의도적 일시 중지입니다. submitted/pending-approval은 아직 승인되지 않았습니다. routing-failed는 디스패처가 여전히 재시도 중입니다.

왜 양쪽 조건이 필요한가(v0.6.1부터). originating_task_id는 과적재되어 있습니다. 반환 작업에서는 "이것이 그 요청에 대한 답이다"를 의미하지만, 전달 요청에서는 "이 부모로부터 workflow_mode를 상속한다"를 의미합니다. 빌드 에이전트가 자신의 진행 중인 빌드에 대한 감사 요청을 제출할 때 전달하는 값이 바로 이것입니다. 첫 번째 조건만 확인해서는 이 둘을 구분할 수 없습니다. 빌드 작업은 빌드 에이전트를 대상으로 하고 빌드 에이전트가 제출자이기 때문입니다. v0.6.0은 첫 번째 검사만 포함한 채 배포되었고, 한 시간 안에 진행 중인 빌드 작업을 종료해 버렸습니다.

진짜 반환은 대칭적이지만, 전달 요청은 그렇지 않습니다.

부모

새 작업

실행?

반환

감사 developer → security

security → developer

예 — 두 조건 모두 충족

전달 요청

빌드 research → developer

감사 요청 developer → security

아니요 — research != security

approved 상태의 부모는 먼저 in-progress를 거치므로, 그 이력은 순간이동처럼 보이지 않고 '수행된 후 종료됨'으로 읽힙니다.

이 기능은 안전장치이지 기본 경로가 아닙니다. 에이전트는 여전히 자신의 작업을 명시적으로 종료해야 합니다. 그래야 에이전트 자신의 메모가 이력에 남습니다. 이 기능은 auto-closed: return task <id> submitted만 기록합니다. 자동 종료 내부의 어떤 실패도 경고 수준으로 기록되고 제출은 정상적으로 반환됩니다. 자동 종료는 그 부수 효과인 제출을 절대 실패시킬 수 없습니다.

list_tasks

list_tasks(
    target_agent="deploy-agent",  # optional
    source_agent="research",  # optional
    status="approved,in-progress",  # comma-separated, optional
    task_type="build",  # optional
    include_archived=False,  # include archive/ subdirectory
    limit=20,  # max 200
)
# → list of task dicts, sorted by created descending

인식할 수 없는 status는 오류입니다. 빈 결과가 아닙니다(v0.6.0부터). 예전에는 조용히 필터링되었습니다. 그래서 여기에는 존재하지 않는 상태인 status="pending"으로 검색한 작업이 '할 일 없음'과 구분할 수 없는 []를 수개월 동안 반환했습니다. 빈 목록은 올바르게 만들어진 질문에 대한 타당한 답입니다. 오타를 빈 큐와 구분하는 유일한 방법은 오타를 거부하는 것입니다. 공백과 끝의 쉼표는 여전히 허용되며, 빈 문자열은 여전히 필터 없음을 의미합니다.

종료 상태의 작업 중 ttl_days가 지난 작업은 제외됩니다. TTL 보관에 대한 권한은 디스패처에 있지만, list_tasks는 에이전트가 오래된 항목을 처리하지 않도록 완료된 기록을 선제적으로 필터링합니다.

비종료 작업은 결코 TTL 필터링되지 않습니다(v0.8.1, vikunja#395부터). 진행 중인 작업은 ttl_days가 지나면 목록에서 사라졌지만 여전히 디스크에 남아 누군가를 기다리고 있었습니다. 이는 방어 장치라기보다 사각지대였고, 이미 큐 점검 중 이 도구가 13개라고 보고한 곳에서 17개의 좌초된 작업을 발견하게 한 원인이었습니다. 누군가의 책임으로 남아 있는 작업은 시계에 의해 숨겨져서는 안 됩니다. 오래된 진행 중 작업을 받은 에이전트는 이를 판단할 수 있지만, 볼 수 없는 작업에 대해 아무도 행동할 수 없습니다.

보류된 작업은 TTL 필터에서 면제됩니다. 보류는 '이건 잠시 멈추고, 나중에 다시 보겠다'는 의도적인 행동입니다. 보류된 작업이 조용히 목록에서 만료된다면 그 상태의 의미가 사라집니다.

get_task

get_task(task_id="a7f3d2c1-1234-5678-abcd-000000000000")
# → full task dict, or {"ok": false, "error": "not found"}

먼저 기본 큐를 검색하고, 그다음 archive/를 검색합니다. 전체 UUID가 필요합니다. 접두어 일치는 없습니다.

update_task

update_task(
    task_id="a7f3d2c1-1234-5678-abcd-000000000000",
    status="in-progress",  # see transition table below
    actor="deploy-agent",
    note="Claimed task, starting build.",
    output=None,  # written to result.output on completed/failed
)
# → {"ok": true, "task_id": "<uuid>"} or {"ok": false, "error": "..."}

소유권 검사(v0.5.0부터): actor는 작업의 target_agent와 같아야 하거나 "operator"여야 합니다. 그 외의 액터는 거부됩니다. 이로써 작업이 할당된 에이전트가 아닌 다른 에이전트가 작업을 요청하거나 완료할 수 있었던 공백이 해소됩니다.

유효한 전이:

시작 상태

도착 상태

approved

in-progress

in-progress

completed

모든 비종료 상태

failed

비종료 상태: submitted, pending-approval, approved, in-progress, parked, routing-failed. 종료 상태: completed, failed, cancelled.

routing-failed는 디스패처가 작성하는 상태이며, 위의 Any non-terminal → failed 행에서 의도적으로 제외되었습니다. 에이전트는 디스패처가 아직 재시도 중인 작업을 종료 상태로 실패시킬 수 없어야 합니다. 이 상태는 아래 운영자 전이(cancelled, parked, override)의 일반적인 출처입니다.

retry_policy는 디스패처 소유입니다. update_task는 절대 건드리지 않습니다.

운영자 전이 (set_task_status)

update_task보다 범위는 넓지만 여전히 감사되고 제한됩니다.

시작 상태

도착 상태

메모

submitted / pending-approval

approved

표준

모든 비종료 상태

cancelled

표준 (cancel_task로도 가능)

모든 비종료 상태

parked

표준 (park_task로도 가능)

모든 비종료 상태

모든 비종료 상태

allow_override=True 및 비어 있지 않은 메모 필요("놓친 작업 진행" 오버라이드)

모든 인식 불가 상태

모든 유효 상태

allow_override=True 및 비어 있지 않은 메모 필요(복구 경로)

종료 상태의 작업은 운영자에게도 불변입니다. 모든 운영자 변경은 actor + note와 함께 기록 항목을 추가합니다.

복구 경로는 큐 디렉터리에 작성자가 둘 이상 있기 때문에 존재합니다. 상태가 이 서버의 어휘에 완전히 포함되지 않는 레코드 — 역사적인 complete 오타 또는 아직 여기서 허용되지 않은 향후 디스패처 상태 — 는 다른 모든 분기로는 도달할 수 없으며, 그대로 두면 영원히 멈춰 있을 것입니다. 복구는 항상 작업을 잘못된 상태 에서 벗어나게만 합니다. 대상 상태는 여전히 유효해야 하며, 기록 항목은 repaired_from을 기록합니다. routing-failed는 더 이상 이 경로가 필요하지 않습니다. 이제 일급 비종료 상태이기 때문입니다(위 참조). 표준 cancelled/parked 행이나 일반 오버라이드 행을 통해 도달할 수 있습니다.

park_task / unpark_task

park_task(task_id="...", actor="operator", note="waiting on upstream fix")
# → {"ok": true, "task_id": "<uuid>"}

unpark_task(task_id="...", actor="operator", status=None)
# → returns the task to the status it was parked from

보류는 상태만 변경합니다. YAML은 절대 이동하지 않습니다. 작업은 list_tasks에 계속 표시되고, TTL 만료에서 면제되며, 아무도 가져가지 않습니다. 디스패처의 픽업 루프가 submittedrouting-failed만 일치시키기 때문입니다. 이전 상태는 parked_from에 기록되고 나갈 때 지워지므로 절대 오래된 상태로 남지 않습니다. unpark_taskstatus를 전달하면 작업이 왔던 곳이 아닌 다른 곳으로 보낼 수 있습니다. parked_from이 없는 직접 YAML 작성자가 보류한 작업에는 이 매개변수가 필요합니다.

보류는 '지금은 아니지만, 이걸 잃지 마라'는 뜻입니다. 오랫동안 유휴 상태인 작업이 반드시 방치를 의미하지는 않습니다. parked는 의도적인 북마크와 진짜 버려진 것을 구분하는 어휘입니다.

amend_task

amend_task(
    task_id="...",
    amendment="Preflight answered the open question — FastMCP mount() is live-linked.",
    actor="research",  # the task's source_agent, or "operator"
    reason="preflight ran after queuing",
)
# → {"ok": true, "task_id": "...", "amendment_count": 1, "agent_may_have_started": false}

작업이 큐에 들어가면 설명은 불변입니다. 큐에 넣은 후 시작하기 전 사이에 무언가가 변경되면 — 사전 점검이 미해결 질문에 답하고, 의존성이 도착하고, 리뷰어가 오류를 발견하고, 범위가 좁혀지는 등 — 수정 사항이 갈 곳이 없으며, 작업 설명을 신뢰하는 에이전트는 잘못된 일을 하게 됩니다.

amend_task는 그 공백을 추가 전용으로 메웁니다. payload.description은 절대 변경되지 않습니다. 수정 사항은 payload.amendments 아래에 {timestamp, actor, reason, text} 형태로 누적되며, 읽는 쪽은 설명 뒤에 이를 렌더링합니다. 작업이 원래 요청한 내용은 기록에 남아 있습니다.

규칙

동작

수정 가능 대상

작업의 source_agent 또는 operator. 대상 에이전트는 거부됨 — 지시받은 내용을 다시 작성할 수 없으며, cancelledoperator 전용으로 만드는 것과 동일한 신뢰 경계가 적용됩니다.

시점

pending, approved, in-progress, parked 상태의 모든 비종결 작업. 종결 및 보관된 작업은 거부됨.

in-progress

허용됨 — 가장 중요한 사례 — 그러나 응답은 agent_may_have_started: true를 설정합니다. 에이전트가 이미 원본을 읽었을 수 있으므로, out-of-band로 알려야 합니다.

범위

작업당 10개의 수정안, 각각 4096자.

범위 확장 지침: 작업에 대한 수정안이 한두 개를 초과하면 취소하고 다시 큐에 넣는 신호입니다. 누적하지 마십시오. 범위 제한은 예산이 아니라 안전장치입니다.

Related MCP server: task-manager-mcp

상태 수명주기

submitted → [pending-approval] → approved → in-progress → completed
                                                 ↓
                                              failed

routing-failed  # dispatcher-written on a failed dispatch attempt; non-terminal

Any non-terminal ──(operator)──> cancelled     # graceful dismissal, record kept
Any non-terminal <──(operator)──> parked       # pause; stays listed, TTL-exempt

디스패처는 submitted → approved/pending-approval 전환을 소유하며, 전송 시도가 실패하면 routing-failed를 기록합니다(자체 일정에 따라 재시도하며, 운영자는 set_task_status를 통해 취소, 보류, 강제 전환할 수도 있습니다). 에이전트는 approved → in-progress → completed(또는 failed)를 소유합니다 — routing-failedupdate_task로 도달할 수 없습니다. 운영자는 cancelled, parked, 감사된 상태 재정의를 소유합니다. 승인 게이팅은 에이전트 매니페스트와 requires_approval 필드에 의해 제어됩니다.

모든 작업은 자체 대상 에이전트에 의해 종결됩니다. 이는 update_task의 소유권 검사에서 비롯되며, 새 교차 에이전트 워크플로우를 연결할 때 명심해야 할 유일한 규칙입니다: 요청을 제출하는 에이전트는 요청이 다른 대상을 지정하므로 이를 종결할 수 없습니다. 따라서 요청/응답 쌍은 수신 에이전트가 자체 항목을 클레임하고 종결해야 합니다 — 두 번의 호출이 필요하며, completedin-progress에서만 도달할 수 있습니다. 자동 종결은 그렇지 못한 경우의 안전장치이며, 이를 대체하는 것이 아닙니다.

HTTP 제어 API

MCP가 아닌 클라이언트(CloudCLI 플러그인과 Matrix 봇)는 Python 코어를 가져올 수 없으므로, 모든 변경 작업은 동일한 포트 8485에 마운트된 FastMCP 커스텀 라우트로 구성된 얇은 HTTP 제어 API를 통해 이루어집니다. 각 엔드포인트는 위의 도구 핸들러에 위임하여 전환 검증, fcntl 잠금, 원자적 쓰기를 상속합니다 — 따라서 전체 시스템에는 정확히 하나의 검증된 쓰기 경로가 존재합니다.

메서드

경로

위임 대상

POST

/tasks/{id}/approve

set_task_status(approved)

POST

/tasks/{id}/cancel

cancel_task

POST

/tasks/{id}/status

set_task_status (본문: status, note, allow_override)

POST

/tasks/{id}/park

park_task

POST

/tasks/{id}/unpark

unpark_task (본문: 선택적 status)

POST

/tasks/{id}/amend

amend_task (본문: amendment, 선택적 reason)

POST

/tasks/{id}/update

update_task (본문: status, note, output, 선택적 on_behalf_of)

GET

/queue/summary

상태별 활성 작업 수

본문 필드: 상태 라우트의 경우 notestatus / allow_override, amend의 경우 amendment / reason, update의 경우 status / output / on_behalf_of. 응답은 표준 결과를 매핑합니다: 200 성공, 404 찾을 수 없음, 400 검증/전환 오류.

actor는 이 모든 라우트에서 operator로 고정되며 본문에서 읽지 않습니다 (v0.8.0부터). 이전에는 body.get("actor", "operator")였습니다 — 실제로는 정상적으로 동작했지만, 호출자가 명시적으로 선택하지 않은 경우 운영자 신원을 암묵적으로 상속하게 만들었습니다. 고정한다는 것은 미래의 비운영자 클라이언트가 모든 소유권 검사에서 면제되는 신원을 조용히 획득할 수 없음을 의미합니다.

운영자 스윕 — POST /tasks/{id}/update

다른 에이전트의 작업에 대한 종결 전환의 유일한 경로입니다. v0.8.0이 부정직한 버전을 폐쇄했기 때문에 존재합니다: 에이전트는 해당 에이전트의 이름을 actor로 전달하여 좌초된 작업을 정리하곤 했습니다. 이제 actoroperator에 바인딩하면 set_task_status가 종결 전환을 만들 수 없고 update_task 도구가 해결된 신원을 요구하므로, 이 라우트가 없으면 모든 좌초된 작업에 운영자가 수동으로 개입해야 합니다.

on_behalf_of에 작업을 소유한 에이전트의 이름을 전달하십시오. 핸들러는 이를 작업의 실제 target_agent와 대조하여 검증합니다(불일치 시 400 — 잘못 식별된 작업을 종결하는 운영자는 침묵 속에 실패하기보다 명시적으로 통보받아야 하며, 실수가 의도된 것으로 기록되지 않아야 합니다). 그리고 이름을 기록합니다: completed_by에는 operator를, history[].actor에는 on_behalf_of를 기록합니다.

history:
  - timestamp: ...
    status: completed
    actor: operator
    on_behalf_of: developer
    note: "stranded; swept during queue cleanup"

스윕은 나중에 스윕으로 읽혀야 합니다 — 에이전트가 조용히 자신의 작업을 종결한 것으로 보여서는 안 됩니다. on_behalf_of는 선택 사항입니다 — 생략하면 운영자가 자신의 이름으로 행동하는 것입니다 — 그러나 비운영자 actor에 대해서는 명시적으로 거부됩니다.

GET /queue/summary{"ok": true, "counts": {...}, "active": N, "total": N}을 반환합니다. 여기서 active는 비종결 총계입니다(이제 routing-failed 포함, 이름별 집계). 서버 어휘에 없는 상태는 삭제되지 않고 "unknown" 버킷에 포함됩니다 — 따라서 다른 직접 YAML 작성자가 기록한 레코드도 대시보드에서 계속 표시됩니다.

인증: 커스텀 라우트는 전송의 bearer 인증을 우회하므로, 공유 시크릿 헤더가 관문입니다 — 그리고 이 라우트는 의도적으로 그 경계 밖에 있습니다. 왜냐하면 그것이 운영자 표면이기 때문입니다:

  • 모든 변경에 X-Task-Queue-Secret: $TASK_QUEUE_API_SECRET을 보내십시오.

  • 서버는 상수 시간 비교(hmac.compare_digest)로 비교하고, 시크릿이 누락되었거나, 잘못되었거나, 구성되지 않은 경우 폐쇄적 실패(401)합니다.

  • 시크릿은 저장소 외부의 운영자 관리 env 파일에 있으며, env_file을 통해 컨테이너와 각 클라이언트 환경에 주입됩니다 — 소스에 커밋되지 않습니다.

배포

Docker(프로덕션)

services:
  task-queue-mcp:
    image: task-queue-mcp:latest
    container_name: task-queue-mcp
    ports:
      # The loopback bind is load-bearing, not cosmetic. The MCP transport on this port
      # is unauthenticated (see Trust model below), so publishing it as "8485:8485"
      # would expose an unauthenticated queue-mutation endpoint to your whole LAN.
      - "127.0.0.1:8485:8485"
    volumes:
      - ~/.claude/task-queue:/task-queue   # host queue directory
    environment:
      - TASK_QUEUE_DIR=/task-queue
      # 0.0.0.0 here is the *container-internal* bind and must stay wide, or the port
      # mapping above has nothing to forward to. The host-side bind is what limits reach.
      - MCP_HOST=0.0.0.0
      - MCP_PORT=8485
    cap_drop: [ALL]
    security_opt: [no-new-privileges:true]
    read_only: true
    tmpfs: [/tmp]
    user: "1000:1000"
    restart: unless-stopped
    networks:
      - agent-net

컨테이너는 작업 큐 디렉토리만 읽기-쓰기로 마운트합니다. 나머지 파일 시스템은 읽기 전용입니다. /tmp는 임시 스크래치 공간용 tmpfs입니다.

Claude Code settings.json

{
  "mcpServers": {
    "task-queue-mcp": {
      "type": "url",
      "url": "http://localhost:8485/mcp"
    }
  }
}

환경 변수

변수

기본값

설명

TASK_QUEUE_DIR

/task-queue

컨테이너 내부의 작업 큐 디렉토리 경로

MCP_HOST

0.0.0.0

HTTP 서버 바인드 호스트

MCP_PORT

8485

HTTP 서버 포트

TASK_QUEUE_API_SECRET

HTTP 제어 API용 공유 시크릿. 제어 API 변경에는 필수 — 설정되지 않으면 폐쇄적 실패(401). MCP 도구 자체는 이를 사용하지 않습니다.

TASK_QUEUE_TOKEN_<AGENT>

호출 에이전트 하나의 bearer 토큰(예: TASK_QUEUE_TOKEN_DEVELOPER). 최소 하나는 필수 — HTTP 전송은 없으면 시작을 거부합니다. 접미사는 에이전트 신원이 되며, 소문자로 변환되고 _-로 변환됩니다(TASK_QUEUE_TOKEN_DOC_HEALTHdoc-health).

각 에이전트는 자체 토큰이 필요합니다 — 토큰이 호출자를 식별하므로, 두 에이전트가 토큰을 공유하면 속성 추적이 무의미해집니다. 서버는 공유 토큰, 빈 값, 16자 미만의 토큰, 또는 예약된 operator 신원용으로 발급된 토큰으로는 시작을 거부합니다. 다음으로 생성하십시오:

python -c "import secrets; print(secrets.token_urlsafe(32))"

호출자는 표준 bearer 헤더로 제시합니다:

headers:
  Authorization: "Bearer ${TASK_QUEUE_TOKEN}"

빌드

docker build -t task-queue-mcp:latest .

개발

Python 3.11+ 필요.

pip install -e ".[dev]"

# Lint + format (Baseline gate)
ruff check .
ruff format --check .

# Tests with coverage (gate: >=80%)
python -m pytest --cov=src --cov-report=term-missing

# Run server locally against a local task-queue directory
TASK_QUEUE_DIR=~/.claude/task-queue python -m src.server

테스트 스위트는 모든 도구와 HTTP 제어 API를 다룹니다 — 검증 경계 사례, 적대적 YAML 문자열, 불법 전환, park/unpark 왕복, amend_task 권한 부여(거부된 대상 에이전트 포함), 운영자 재정의 감사, 어휘 외 상태 복구, 공유 시크릿 게이트(누락/잘못된 시크릿 → 401). 모든 쓰기는 YAML 주입을 방지하기 위해 문자열 보간이 아닌 yaml.dump를 사용합니다.

보안

포트 8485의 두 표면 모두 자격 증명이 필요합니다:

  • MCP 도구 경로(/mcp) — 에이전트별 bearer 토큰, FastMCP의 StaticTokenVerifier로 검증. 누락 또는 알 수 없는 토큰 → 401. 전송은 토큰이 구성되지 않은 상태로 시작을 거부하므로 조용히 열린 채 실패할 수 없습니다.

  • HTTP 제어 라우트(/tasks/..., /queue/summary) — 공유 시크릿 헤더(X-Task-Queue-Secret, 상수 시간 비교, 폐쇄적 실패). HTTP 제어 API 참조.

컨테이너는 UID 1000으로 실행되며 cap_drop: ALL, no-new-privileges, 읽기 전용 루트 파일 시스템(/task-queue만 쓰기 가능)을 사용합니다.

신뢰 모델

v0.7.0까지 MCP 도구 경로는 인증되지 않았습니다. README는 루프백이 충분한 신뢰 경계라고 주장했습니다. 사실이 아니었습니다: 포트가 게시되었을 뿐만 아니라 컨테이너가 공유 Docker 네트워크에 참여하므로 해당 네트워크의 모든 컨테이너가 도구 경로에 도달할 수 있었습니다. 그들 중 누구라도 set_task_status, cancel_task, park_task, unpark_task, amend_task를 호출하면서 임의의 actor — 소유권 검사에서 명시적으로 면제되는 operator를 포함하여 — 를 주장할 수 있었습니다. 이로 인해 completed_byhistory[].actor는 증거가 아닌 주장이 되었습니다. (vikunja#387)

v0.7.0이 그 경로를 폐쇄합니다. 각 에이전트는 고유한 토큰을 보유하므로, 토큰은 호출자를 인증하고 식별합니다. 별도의 신원 헤더는 의도적으로 없습니다: 에이전트가 토큰을 보유하면 직접 요청에서 원하는 헤더를 설정할 수 있으므로, 헤더에서 파생된 신원은 토큰에서 파생된 신원과 경쟁하는 엄격히 약한 두 번째 채널이 됩니다. 두 개의 신원 소스가 아니라 하나입니다.

이것이 제공하는 것과 제공하지 않는 것. 이는 자체 도구 표면을 통해 작동하는 잘못되었거나 프롬프트가 주입된 에이전트를 포함하며, 감사 추적이 의미하는 바를 실제로 보장합니다. 이는 의도적으로 자격 증명을 찾아다니는 에이전트에 대한 경계가 아닙니다: 에이전트가 셸 도구를 보유하고 비밀 파일을 소유한 동일한 OS 사용자로 실행되는 경우, 호스트의 모든 토큰은 그들 중 누구라도 읽을 수 있습니다. 이를 차단하려면 에이전트별 OS 사용자 또는 자격 증명 브로커가 필요하며, 이 서버의 범위를 벗어납니다.

operator 신원은 오직 HTTP 제어 경로에서만 접근할 수 있습니다. TASK_QUEUE_TOKEN_OPERATOR는 시작 시 거부됩니다. operator는 모든 소유권 검사에서 면제되며, 에이전트 대상 전송에서 이 토큰을 발급하면 보유자에게 전체 큐를 넘겨주게 되기 때문입니다.

신원 바인딩 (v0.8.0부터)

actor는 호출자로부터 가져오는 것이 아니라 베어러 토큰에서 파생됩니다. 인증된 신원과 일치하지 않는 이름을 전달하면 조용히 수정되는 대신 거부됩니다 — 호출에 잘못된 이름이 있는 것은 표면화할 가치가 있는 버그입니다. 생략하는 것은 괜찮습니다. 토큰에서 자동으로 채워집니다.

이는 submit_tasksource_agent에도 적용됩니다. 이는 단순한 라벨이 아니라 신원 주장입니다: 제출 시 자동 종료는 source_agent/target_agent에서 실행할지 여부를 결정하므로, 이를 스푸핑하면 update_task를 호출하지 않고도 다른 에이전트의 작업을 종결 상태로 만들 수 있습니다.

도구

호출할 수 있는 대상

submit_task, list_tasks, get_task

인증된 모든 에이전트 (source_agent는 호출자에 바인딩됨)

update_task

작업의 target_agent 또는 operator

park_task, unpark_task

작업의 target_agent 또는 operator

amend_task

작업의 source_agent 또는 operator

set_task_status, cancel_task

operator 전용 — 모든 에이전트 신원에 대해 거부됨

set_task_status는 operator 전용입니다. 그 이유는 allow_override 경로가 작업을 두 비종결 상태 사이에서 이동시킬 수 있으며, 이것이 전이 규칙을 충족하는 대신 우회하여 작업을 이동시키는 방법이기 때문입니다. cancel_task는 다른 사람의 작업에 대한 종결적이고 되돌릴 수 없는 판단입니다. 에이전트가 자신의 작업을 포기하는 경우 update_task를 통해 사유와 함께 failed로 표시합니다.

작업 파일 스키마

작업은 ~/.claude/task-queue/ 디렉토리의 YAML 파일이며, YYYYMMDD-HHMMSS-<uuid-prefix>.yml 형식으로 이름이 지정됩니다. 모든 쓰기는 원자적입니다 (.tmp에 쓴 다음 os.rename()). fcntl.flock을 통한 작업별 파일 잠금은 동시 MCP 호출과 디스패처 간의 경합을 방지합니다.

전체 스키마 및 수명 주기 문서는 homelab-agent 컴포넌트 문서를 참조하세요.

관련 자료

A
license - permissive license
Not graded
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
1wRelease cycle
8Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Model Context Protocol server for Task Management. This allows Claude Desktop (or any MCP client) to manage and execute tasks in a queue-based system.
    10
    154
    215
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    A task manager MCP server that demonstrates all three MCP primitives (tools, resources, prompts). Enables users to manage tasks, read task summaries and details, and run structured planning/review prompts through natural language.
  • F
    license
    A
    quality
    C
    maintenance
    A production-ready MCP server for task management, enabling LLMs to create, list, and manage tasks via tools and resources, with support for local stdio and cloud Streamable HTTP deployment.
    5

View all related MCP servers

Related MCP Connectors

  • Project management MCP for AI agents with safe task reads and writes.

  • Reliable async execution for agent tool calls: schema gating, retries, idempotency, audit trail.

  • Coordinate multiple AI agents over MCP: atomic claims, leases, shared ledger, handoffs, tasks.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TadMSTR/task-queue-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server