mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-05-18 07:28:11 +00:00
Compare commits
2 Commits
docs/stop-
...
iris/fix/m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7780565f1b | ||
|
|
52c4e4a309 |
@@ -1,8 +0,0 @@
|
||||
---
|
||||
title: "POST /stop/{kickoff_id}"
|
||||
description: "إيقاف تنفيذ الطاقم الجاري"
|
||||
openapi: "/enterprise-api.en.yaml POST /stop/{kickoff_id}"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
|
||||
@@ -495,8 +495,7 @@
|
||||
"en/api-reference/inputs",
|
||||
"en/api-reference/kickoff",
|
||||
"en/api-reference/resume",
|
||||
"en/api-reference/status",
|
||||
"en/api-reference/stop"
|
||||
"en/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -965,8 +964,7 @@
|
||||
"en/api-reference/inputs",
|
||||
"en/api-reference/kickoff",
|
||||
"en/api-reference/resume",
|
||||
"en/api-reference/status",
|
||||
"en/api-reference/stop"
|
||||
"en/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1435,8 +1433,7 @@
|
||||
"en/api-reference/inputs",
|
||||
"en/api-reference/kickoff",
|
||||
"en/api-reference/resume",
|
||||
"en/api-reference/status",
|
||||
"en/api-reference/stop"
|
||||
"en/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1905,8 +1902,7 @@
|
||||
"en/api-reference/inputs",
|
||||
"en/api-reference/kickoff",
|
||||
"en/api-reference/resume",
|
||||
"en/api-reference/status",
|
||||
"en/api-reference/stop"
|
||||
"en/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -2376,8 +2372,7 @@
|
||||
"en/api-reference/inputs",
|
||||
"en/api-reference/kickoff",
|
||||
"en/api-reference/resume",
|
||||
"en/api-reference/status",
|
||||
"en/api-reference/stop"
|
||||
"en/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -2845,8 +2840,7 @@
|
||||
"en/api-reference/inputs",
|
||||
"en/api-reference/kickoff",
|
||||
"en/api-reference/resume",
|
||||
"en/api-reference/status",
|
||||
"en/api-reference/stop"
|
||||
"en/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -3317,8 +3311,7 @@
|
||||
"en/api-reference/inputs",
|
||||
"en/api-reference/kickoff",
|
||||
"en/api-reference/resume",
|
||||
"en/api-reference/status",
|
||||
"en/api-reference/stop"
|
||||
"en/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -3803,8 +3796,7 @@
|
||||
"pt-BR/api-reference/inputs",
|
||||
"pt-BR/api-reference/kickoff",
|
||||
"pt-BR/api-reference/resume",
|
||||
"pt-BR/api-reference/status",
|
||||
"pt-BR/api-reference/stop"
|
||||
"pt-BR/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -4258,8 +4250,7 @@
|
||||
"pt-BR/api-reference/inputs",
|
||||
"pt-BR/api-reference/kickoff",
|
||||
"pt-BR/api-reference/resume",
|
||||
"pt-BR/api-reference/status",
|
||||
"pt-BR/api-reference/stop"
|
||||
"pt-BR/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -4713,8 +4704,7 @@
|
||||
"pt-BR/api-reference/inputs",
|
||||
"pt-BR/api-reference/kickoff",
|
||||
"pt-BR/api-reference/resume",
|
||||
"pt-BR/api-reference/status",
|
||||
"pt-BR/api-reference/stop"
|
||||
"pt-BR/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -5168,8 +5158,7 @@
|
||||
"pt-BR/api-reference/inputs",
|
||||
"pt-BR/api-reference/kickoff",
|
||||
"pt-BR/api-reference/resume",
|
||||
"pt-BR/api-reference/status",
|
||||
"pt-BR/api-reference/stop"
|
||||
"pt-BR/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -5622,8 +5611,7 @@
|
||||
"pt-BR/api-reference/inputs",
|
||||
"pt-BR/api-reference/kickoff",
|
||||
"pt-BR/api-reference/resume",
|
||||
"pt-BR/api-reference/status",
|
||||
"pt-BR/api-reference/stop"
|
||||
"pt-BR/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -6076,8 +6064,7 @@
|
||||
"pt-BR/api-reference/inputs",
|
||||
"pt-BR/api-reference/kickoff",
|
||||
"pt-BR/api-reference/resume",
|
||||
"pt-BR/api-reference/status",
|
||||
"pt-BR/api-reference/stop"
|
||||
"pt-BR/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -6531,8 +6518,7 @@
|
||||
"pt-BR/api-reference/inputs",
|
||||
"pt-BR/api-reference/kickoff",
|
||||
"pt-BR/api-reference/resume",
|
||||
"pt-BR/api-reference/status",
|
||||
"pt-BR/api-reference/stop"
|
||||
"pt-BR/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -7029,8 +7015,7 @@
|
||||
"ko/api-reference/inputs",
|
||||
"ko/api-reference/kickoff",
|
||||
"ko/api-reference/resume",
|
||||
"ko/api-reference/status",
|
||||
"ko/api-reference/stop"
|
||||
"ko/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -7496,8 +7481,7 @@
|
||||
"ko/api-reference/inputs",
|
||||
"ko/api-reference/kickoff",
|
||||
"ko/api-reference/resume",
|
||||
"ko/api-reference/status",
|
||||
"ko/api-reference/stop"
|
||||
"ko/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -7963,8 +7947,7 @@
|
||||
"ko/api-reference/inputs",
|
||||
"ko/api-reference/kickoff",
|
||||
"ko/api-reference/resume",
|
||||
"ko/api-reference/status",
|
||||
"ko/api-reference/stop"
|
||||
"ko/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -8430,8 +8413,7 @@
|
||||
"ko/api-reference/inputs",
|
||||
"ko/api-reference/kickoff",
|
||||
"ko/api-reference/resume",
|
||||
"ko/api-reference/status",
|
||||
"ko/api-reference/stop"
|
||||
"ko/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -8896,8 +8878,7 @@
|
||||
"ko/api-reference/inputs",
|
||||
"ko/api-reference/kickoff",
|
||||
"ko/api-reference/resume",
|
||||
"ko/api-reference/status",
|
||||
"ko/api-reference/stop"
|
||||
"ko/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -9362,8 +9343,7 @@
|
||||
"ko/api-reference/inputs",
|
||||
"ko/api-reference/kickoff",
|
||||
"ko/api-reference/resume",
|
||||
"ko/api-reference/status",
|
||||
"ko/api-reference/stop"
|
||||
"ko/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -9829,8 +9809,7 @@
|
||||
"ko/api-reference/inputs",
|
||||
"ko/api-reference/kickoff",
|
||||
"ko/api-reference/resume",
|
||||
"ko/api-reference/status",
|
||||
"ko/api-reference/stop"
|
||||
"ko/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -10327,8 +10306,7 @@
|
||||
"ar/api-reference/inputs",
|
||||
"ar/api-reference/kickoff",
|
||||
"ar/api-reference/resume",
|
||||
"ar/api-reference/status",
|
||||
"ar/api-reference/stop"
|
||||
"ar/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -10794,8 +10772,7 @@
|
||||
"ar/api-reference/inputs",
|
||||
"ar/api-reference/kickoff",
|
||||
"ar/api-reference/resume",
|
||||
"ar/api-reference/status",
|
||||
"ar/api-reference/stop"
|
||||
"ar/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -11261,8 +11238,7 @@
|
||||
"ar/api-reference/inputs",
|
||||
"ar/api-reference/kickoff",
|
||||
"ar/api-reference/resume",
|
||||
"ar/api-reference/status",
|
||||
"ar/api-reference/stop"
|
||||
"ar/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -11728,8 +11704,7 @@
|
||||
"ar/api-reference/inputs",
|
||||
"ar/api-reference/kickoff",
|
||||
"ar/api-reference/resume",
|
||||
"ar/api-reference/status",
|
||||
"ar/api-reference/stop"
|
||||
"ar/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -12194,8 +12169,7 @@
|
||||
"ar/api-reference/inputs",
|
||||
"ar/api-reference/kickoff",
|
||||
"ar/api-reference/resume",
|
||||
"ar/api-reference/status",
|
||||
"ar/api-reference/stop"
|
||||
"ar/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -12660,8 +12634,7 @@
|
||||
"ar/api-reference/inputs",
|
||||
"ar/api-reference/kickoff",
|
||||
"ar/api-reference/resume",
|
||||
"ar/api-reference/status",
|
||||
"ar/api-reference/stop"
|
||||
"ar/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -13127,8 +13100,7 @@
|
||||
"ar/api-reference/inputs",
|
||||
"ar/api-reference/kickoff",
|
||||
"ar/api-reference/resume",
|
||||
"ar/api-reference/status",
|
||||
"ar/api-reference/stop"
|
||||
"ar/api-reference/status"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
title: "POST /stop/{kickoff_id}"
|
||||
description: "Stop a running crew execution"
|
||||
openapi: "/enterprise-api.en.yaml POST /stop/{kickoff_id}"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
|
||||
@@ -146,36 +146,6 @@ curl -X GET \
|
||||
https://your-crew-url.crewai.com/status/abcd1234-5678-90ef-ghij-klmnopqrstuv
|
||||
```
|
||||
|
||||
## Stopping a Running Execution
|
||||
|
||||
You can stop or cancel a running crew or flow execution at any time using the stop endpoint. This is useful when you need to abort a long-running execution or cancel one that is no longer needed.
|
||||
|
||||
### Stop an Execution
|
||||
|
||||
Send a POST request with the `kickoff_id` of the execution you want to stop:
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H "Authorization: Bearer YOUR_CREW_TOKEN" \
|
||||
https://your-crew-url.crewai.com/stop/abcd1234-5678-90ef-ghij-klmnopqrstuv
|
||||
```
|
||||
|
||||
**Success Response:**
|
||||
|
||||
```json
|
||||
{"status": "stopped", "kickoffId": "abcd1234-5678-90ef-ghij-klmnopqrstuv"}
|
||||
```
|
||||
|
||||
**Error Response** (when the execution has already finished):
|
||||
|
||||
```json
|
||||
{"detail": "Cannot stop execution. Current state: SUCCESS"}
|
||||
```
|
||||
|
||||
<Note>
|
||||
You cannot stop executions that have already completed (`SUCCESS`), failed (`FAILURE`), or been revoked (`REVOKED`). The API returns a `400` status code in those cases.
|
||||
</Note>
|
||||
|
||||
## Handling Executions
|
||||
|
||||
### Long-Running Executions
|
||||
|
||||
@@ -36,7 +36,6 @@ info:
|
||||
1. **Discover inputs** using `GET /inputs`
|
||||
2. **Start execution** using `POST /kickoff`
|
||||
3. **Monitor progress** using `GET /{kickoff_id}/status`
|
||||
4. **Stop execution** (if needed) using `POST /stop/{kickoff_id}`
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: CrewAI Support
|
||||
@@ -285,56 +284,6 @@ paths:
|
||||
"500":
|
||||
$ref: "#/components/responses/ServerError"
|
||||
|
||||
/stop/{kickoff_id}:
|
||||
post:
|
||||
summary: Stop Crew Execution
|
||||
description: |
|
||||
**📋 Reference Example Only** - *This shows the request format. To test with your actual crew, copy the cURL example and replace the URL + token with your real values.*
|
||||
|
||||
Stops or cancels a running crew or flow execution. The execution must be in an active state
|
||||
(not SUCCESS, FAILURE, or REVOKED).
|
||||
operationId: stopCrewExecution
|
||||
parameters:
|
||||
- name: kickoff_id
|
||||
in: path
|
||||
required: true
|
||||
description: The kickoff ID of the execution to stop
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: "abcd1234-5678-90ef-ghij-klmnopqrstuv"
|
||||
responses:
|
||||
"200":
|
||||
description: Successfully stopped the execution
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/StopExecutionResponse"
|
||||
example:
|
||||
status: "stopped"
|
||||
kickoffId: "abcd1234-5678-90ef-ghij-klmnopqrstuv"
|
||||
"400":
|
||||
description: Execution is already in a terminal state (SUCCESS, FAILURE, or REVOKED)
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
example:
|
||||
detail: "Cannot stop execution. Current state: SUCCESS"
|
||||
"401":
|
||||
$ref: "#/components/responses/UnauthorizedError"
|
||||
"404":
|
||||
description: Kickoff ID not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
example:
|
||||
error: "Execution not found"
|
||||
message: "No execution found with ID: abcd1234-5678-90ef-ghij-klmnopqrstuv"
|
||||
"500":
|
||||
$ref: "#/components/responses/ServerError"
|
||||
|
||||
/resume:
|
||||
post:
|
||||
summary: Resume Crew Execution with Human Feedback
|
||||
@@ -559,19 +508,6 @@ components:
|
||||
description: Time taken to execute this task in seconds
|
||||
example: 45.2
|
||||
|
||||
StopExecutionResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: ["stopped"]
|
||||
description: Indicates the execution was successfully stopped
|
||||
example: "stopped"
|
||||
kickoffId:
|
||||
type: string
|
||||
description: The kickoff ID of the stopped execution
|
||||
example: "abcd1234-5678-90ef-ghij-klmnopqrstuv"
|
||||
|
||||
Error:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -36,7 +36,6 @@ info:
|
||||
1. **Discover inputs** using `GET /inputs`
|
||||
2. **Start execution** using `POST /kickoff`
|
||||
3. **Monitor progress** using `GET /{kickoff_id}/status`
|
||||
4. **Stop execution** (if needed) using `POST /stop/{kickoff_id}`
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: CrewAI Support
|
||||
@@ -285,56 +284,6 @@ paths:
|
||||
"500":
|
||||
$ref: "#/components/responses/ServerError"
|
||||
|
||||
/stop/{kickoff_id}:
|
||||
post:
|
||||
summary: Stop Crew Execution
|
||||
description: |
|
||||
**📋 Reference Example Only** - *This shows the request format. To test with your actual crew, copy the cURL example and replace the URL + token with your real values.*
|
||||
|
||||
Stops or cancels a running crew or flow execution. The execution must be in an active state
|
||||
(not SUCCESS, FAILURE, or REVOKED).
|
||||
operationId: stopCrewExecution
|
||||
parameters:
|
||||
- name: kickoff_id
|
||||
in: path
|
||||
required: true
|
||||
description: The kickoff ID of the execution to stop
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: "abcd1234-5678-90ef-ghij-klmnopqrstuv"
|
||||
responses:
|
||||
"200":
|
||||
description: Successfully stopped the execution
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/StopExecutionResponse"
|
||||
example:
|
||||
status: "stopped"
|
||||
kickoffId: "abcd1234-5678-90ef-ghij-klmnopqrstuv"
|
||||
"400":
|
||||
description: Execution is already in a terminal state (SUCCESS, FAILURE, or REVOKED)
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
example:
|
||||
detail: "Cannot stop execution. Current state: SUCCESS"
|
||||
"401":
|
||||
$ref: "#/components/responses/UnauthorizedError"
|
||||
"404":
|
||||
description: Kickoff ID not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
example:
|
||||
error: "Execution not found"
|
||||
message: "No execution found with ID: abcd1234-5678-90ef-ghij-klmnopqrstuv"
|
||||
"500":
|
||||
$ref: "#/components/responses/ServerError"
|
||||
|
||||
/resume:
|
||||
post:
|
||||
summary: Resume Crew Execution with Human Feedback
|
||||
@@ -559,19 +508,6 @@ components:
|
||||
description: Time taken to execute this task in seconds
|
||||
example: 45.2
|
||||
|
||||
StopExecutionResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: ["stopped"]
|
||||
description: Indicates the execution was successfully stopped
|
||||
example: "stopped"
|
||||
kickoffId:
|
||||
type: string
|
||||
description: The kickoff ID of the stopped execution
|
||||
example: "abcd1234-5678-90ef-ghij-klmnopqrstuv"
|
||||
|
||||
Error:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -120,46 +120,6 @@ paths:
|
||||
'500':
|
||||
$ref: '#/components/responses/ServerError'
|
||||
|
||||
/stop/{kickoff_id}:
|
||||
post:
|
||||
summary: 실행 중지
|
||||
description: |
|
||||
**📋 참조 예제만 제공** - *요청 형식을 보여줍니다. 실제 호출은 cURL 예제를 복사해 URL과 토큰을 교체하세요.*
|
||||
|
||||
실행 중인 crew 또는 flow 실행을 중지하거나 취소합니다. 실행이 활성 상태여야 합니다
|
||||
(SUCCESS, FAILURE, REVOKED 상태가 아닌 경우).
|
||||
operationId: stopCrewExecution
|
||||
parameters:
|
||||
- name: kickoff_id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
'200':
|
||||
description: 실행을 성공적으로 중지
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/StopExecutionResponse'
|
||||
'400':
|
||||
description: 실행이 이미 종료 상태 (SUCCESS, FAILURE, REVOKED)
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
'401':
|
||||
$ref: '#/components/responses/UnauthorizedError'
|
||||
'404':
|
||||
description: Kickoff ID를 찾을 수 없음
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
'500':
|
||||
$ref: '#/components/responses/ServerError'
|
||||
|
||||
/resume:
|
||||
post:
|
||||
summary: Resume Crew Execution with Human Feedback
|
||||
@@ -354,15 +314,6 @@ components:
|
||||
execution_time:
|
||||
type: number
|
||||
|
||||
StopExecutionResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: ["stopped"]
|
||||
kickoffId:
|
||||
type: string
|
||||
|
||||
Error:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -36,7 +36,6 @@ info:
|
||||
1. **Descubra os inputs** usando `GET /inputs`
|
||||
2. **Inicie a execução** usando `POST /kickoff`
|
||||
3. **Monitore o progresso** usando `GET /{kickoff_id}/status`
|
||||
4. **Pare a execução** (se necessário) usando `POST /stop/{kickoff_id}`
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: CrewAI Suporte
|
||||
@@ -157,46 +156,6 @@ paths:
|
||||
"500":
|
||||
$ref: "#/components/responses/ServerError"
|
||||
|
||||
/stop/{kickoff_id}:
|
||||
post:
|
||||
summary: Parar Execução da Crew
|
||||
description: |
|
||||
**📋 Exemplo de Referência** - *Mostra o formato da requisição. Para testar com sua crew real, copie o cURL e substitua URL + token.*
|
||||
|
||||
Para ou cancela uma execução de crew ou flow em andamento. A execução deve estar em um estado ativo
|
||||
(não SUCCESS, FAILURE ou REVOKED).
|
||||
operationId: stopCrewExecution
|
||||
parameters:
|
||||
- name: kickoff_id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
"200":
|
||||
description: Execução parada com sucesso
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/StopExecutionResponse"
|
||||
"400":
|
||||
description: Execução já em estado terminal (SUCCESS, FAILURE ou REVOKED)
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
"401":
|
||||
$ref: "#/components/responses/UnauthorizedError"
|
||||
"404":
|
||||
description: Kickoff ID não encontrado
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
"500":
|
||||
$ref: "#/components/responses/ServerError"
|
||||
|
||||
/resume:
|
||||
post:
|
||||
summary: Resume Crew Execution with Human Feedback
|
||||
@@ -392,15 +351,6 @@ components:
|
||||
execution_time:
|
||||
type: number
|
||||
|
||||
StopExecutionResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: ["stopped"]
|
||||
kickoffId:
|
||||
type: string
|
||||
|
||||
Error:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
title: "POST /stop/{kickoff_id}"
|
||||
description: "실행 중인 크루 실행 중지"
|
||||
openapi: "/enterprise-api.ko.yaml POST /stop/{kickoff_id}"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
title: "POST /stop/{kickoff_id}"
|
||||
description: "Parar uma execução de crew em andamento"
|
||||
openapi: "/enterprise-api.pt-BR.yaml POST /stop/{kickoff_id}"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ various transport types, similar to OpenAI's Agents SDK.
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from crewai.mcp.filters import ToolFilter
|
||||
from crewai.mcp.transports.stdio import DEFAULT_ALLOWED_COMMANDS
|
||||
|
||||
|
||||
class MCPServerStdio(BaseModel):
|
||||
@@ -44,6 +45,14 @@ class MCPServerStdio(BaseModel):
|
||||
default=None,
|
||||
description="Optional tool filter for filtering available tools.",
|
||||
)
|
||||
allowed_commands: frozenset[str] | None = Field(
|
||||
default=DEFAULT_ALLOWED_COMMANDS,
|
||||
description=(
|
||||
"Optional frozenset of allowed command basenames for security validation. "
|
||||
"Defaults to common runtimes (python, node, npx, uvx, uv, deno, docker). "
|
||||
"Set to None to disable the allowlist check."
|
||||
),
|
||||
)
|
||||
cache_tools_list: bool = Field(
|
||||
default=False,
|
||||
description="Whether to cache the tool list for faster subsequent access.",
|
||||
|
||||
@@ -292,6 +292,7 @@ class MCPToolResolver:
|
||||
command=mcp_config.command,
|
||||
args=mcp_config.args,
|
||||
env=mcp_config.env,
|
||||
allowed_commands=mcp_config.allowed_commands,
|
||||
)
|
||||
server_name = f"{mcp_config.command}_{'_'.join(mcp_config.args)}"
|
||||
elif isinstance(mcp_config, MCPServerHTTP):
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
from crewai.mcp.transports.base import BaseTransport, TransportType
|
||||
from crewai.mcp.transports.http import HTTPTransport
|
||||
from crewai.mcp.transports.sse import SSETransport
|
||||
from crewai.mcp.transports.stdio import StdioTransport
|
||||
from crewai.mcp.transports.stdio import DEFAULT_ALLOWED_COMMANDS, StdioTransport
|
||||
|
||||
|
||||
__all__ = [
|
||||
"BaseTransport",
|
||||
"DEFAULT_ALLOWED_COMMANDS",
|
||||
"HTTPTransport",
|
||||
"SSETransport",
|
||||
"StdioTransport",
|
||||
|
||||
@@ -9,6 +9,22 @@ from typing_extensions import Self
|
||||
|
||||
from crewai.mcp.transports.base import BaseTransport, TransportType
|
||||
|
||||
# Default allowlist for common MCP server runtimes.
|
||||
# Covers the vast majority of MCP server launch commands.
|
||||
# Pass ``allowed_commands=None`` to disable validation entirely.
|
||||
DEFAULT_ALLOWED_COMMANDS: frozenset[str] = frozenset(
|
||||
{
|
||||
"python",
|
||||
"python3",
|
||||
"node",
|
||||
"npx",
|
||||
"uvx",
|
||||
"uv",
|
||||
"deno",
|
||||
"docker",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class StdioTransport(BaseTransport):
|
||||
"""Stdio transport for connecting to local MCP servers.
|
||||
@@ -34,6 +50,7 @@ class StdioTransport(BaseTransport):
|
||||
command: str,
|
||||
args: list[str] | None = None,
|
||||
env: dict[str, str] | None = None,
|
||||
allowed_commands: frozenset[str] | None = DEFAULT_ALLOWED_COMMANDS,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
"""Initialize stdio transport.
|
||||
@@ -42,9 +59,26 @@ class StdioTransport(BaseTransport):
|
||||
command: Command to execute (e.g., "python", "node", "npx").
|
||||
args: Command arguments (e.g., ["server.py"] or ["-y", "@mcp/server"]).
|
||||
env: Environment variables to pass to the process.
|
||||
allowed_commands: Optional frozenset of allowed command basenames.
|
||||
Defaults to ``DEFAULT_ALLOWED_COMMANDS`` which includes common
|
||||
runtimes (python, node, npx, uvx, uv, deno, docker). Pass
|
||||
``None`` to disable the check entirely.
|
||||
**kwargs: Additional transport options.
|
||||
"""
|
||||
super().__init__(**kwargs)
|
||||
|
||||
if allowed_commands is not None:
|
||||
base_command = os.path.basename(command)
|
||||
# Strip extension for Windows compatibility (e.g., python.exe -> python)
|
||||
base_command = os.path.splitext(base_command)[0]
|
||||
if base_command not in allowed_commands:
|
||||
raise ValueError(
|
||||
f"Command '{command}' is not in the allowed commands list: "
|
||||
f"{sorted(allowed_commands)}. "
|
||||
f"To allow this command, add it to allowed_commands or pass "
|
||||
f"allowed_commands=None to disable this check."
|
||||
)
|
||||
|
||||
self.command = command
|
||||
self.args = args or []
|
||||
self.env = env or {}
|
||||
|
||||
28
lib/crewai/tests/mcp/test_stdio_config.py
Normal file
28
lib/crewai/tests/mcp/test_stdio_config.py
Normal file
@@ -0,0 +1,28 @@
|
||||
"""Tests for MCPServerStdio allowed_commands config integration."""
|
||||
|
||||
from crewai.mcp.config import MCPServerStdio
|
||||
from crewai.mcp.transports.stdio import DEFAULT_ALLOWED_COMMANDS
|
||||
|
||||
|
||||
class TestMCPServerStdioConfig:
|
||||
"""Tests for the allowed_commands field on MCPServerStdio."""
|
||||
|
||||
def test_default_allowed_commands(self):
|
||||
"""MCPServerStdio should default to DEFAULT_ALLOWED_COMMANDS."""
|
||||
config = MCPServerStdio(command="python", args=["server.py"])
|
||||
assert config.allowed_commands == DEFAULT_ALLOWED_COMMANDS
|
||||
|
||||
def test_custom_allowed_commands(self):
|
||||
"""Users can override allowed_commands in config."""
|
||||
custom = frozenset({"my-runtime"})
|
||||
config = MCPServerStdio(
|
||||
command="my-runtime", args=[], allowed_commands=custom
|
||||
)
|
||||
assert config.allowed_commands == custom
|
||||
|
||||
def test_none_allowed_commands(self):
|
||||
"""Users can disable the allowlist via config."""
|
||||
config = MCPServerStdio(
|
||||
command="anything", args=[], allowed_commands=None
|
||||
)
|
||||
assert config.allowed_commands is None
|
||||
93
lib/crewai/tests/mcp/test_stdio_transport.py
Normal file
93
lib/crewai/tests/mcp/test_stdio_transport.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""Tests for StdioTransport command allowlist validation."""
|
||||
|
||||
import pytest
|
||||
|
||||
from crewai.mcp.transports.stdio import DEFAULT_ALLOWED_COMMANDS, StdioTransport
|
||||
|
||||
|
||||
class TestStdioTransportAllowlist:
|
||||
"""Tests for the command allowlist feature."""
|
||||
|
||||
def test_default_allowed_commands_contains_common_runtimes(self):
|
||||
"""DEFAULT_ALLOWED_COMMANDS should include all common MCP server runtimes."""
|
||||
expected = {"python", "python3", "node", "npx", "uvx", "uv", "deno", "docker"}
|
||||
assert expected == DEFAULT_ALLOWED_COMMANDS
|
||||
|
||||
def test_allowed_command_passes_validation(self):
|
||||
"""Commands in the default allowlist should be accepted."""
|
||||
for cmd in DEFAULT_ALLOWED_COMMANDS:
|
||||
transport = StdioTransport(command=cmd, args=["server.py"])
|
||||
assert transport.command == cmd
|
||||
|
||||
def test_allowed_command_with_full_path(self):
|
||||
"""Full paths to allowed commands should pass (basename is checked)."""
|
||||
transport = StdioTransport(command="/usr/bin/python3", args=["server.py"])
|
||||
assert transport.command == "/usr/bin/python3"
|
||||
|
||||
def test_disallowed_command_raises_value_error(self):
|
||||
"""Commands not in the allowlist should raise ValueError."""
|
||||
with pytest.raises(ValueError, match="not in the allowed commands list"):
|
||||
StdioTransport(command="malicious-binary", args=["--evil"])
|
||||
|
||||
def test_disallowed_command_with_full_path_raises(self):
|
||||
"""Full paths to disallowed commands should also be rejected."""
|
||||
with pytest.raises(ValueError, match="not in the allowed commands list"):
|
||||
StdioTransport(command="/tmp/evil/script", args=[])
|
||||
|
||||
def test_allowed_commands_none_disables_validation(self):
|
||||
"""Setting allowed_commands=None should disable the check entirely."""
|
||||
transport = StdioTransport(
|
||||
command="any-custom-binary",
|
||||
args=["--flag"],
|
||||
allowed_commands=None,
|
||||
)
|
||||
assert transport.command == "any-custom-binary"
|
||||
|
||||
def test_custom_allowlist(self):
|
||||
"""Users should be able to pass a custom allowlist."""
|
||||
custom = frozenset({"my-server", "python"})
|
||||
|
||||
# Allowed
|
||||
transport = StdioTransport(
|
||||
command="my-server", args=[], allowed_commands=custom
|
||||
)
|
||||
assert transport.command == "my-server"
|
||||
|
||||
# Not allowed
|
||||
with pytest.raises(ValueError, match="not in the allowed commands list"):
|
||||
StdioTransport(command="node", args=[], allowed_commands=custom)
|
||||
|
||||
def test_extended_allowlist(self):
|
||||
"""Users should be able to extend the default allowlist."""
|
||||
extended = DEFAULT_ALLOWED_COMMANDS | frozenset({"my-custom-runtime"})
|
||||
|
||||
transport = StdioTransport(
|
||||
command="my-custom-runtime", args=[], allowed_commands=extended
|
||||
)
|
||||
assert transport.command == "my-custom-runtime"
|
||||
|
||||
# Original defaults still work
|
||||
transport2 = StdioTransport(
|
||||
command="python", args=["server.py"], allowed_commands=extended
|
||||
)
|
||||
assert transport2.command == "python"
|
||||
|
||||
def test_error_message_includes_sorted_allowed_commands(self):
|
||||
"""The error message should list the allowed commands for discoverability."""
|
||||
with pytest.raises(ValueError) as exc_info:
|
||||
StdioTransport(command="bad-cmd", args=[])
|
||||
|
||||
error_msg = str(exc_info.value)
|
||||
assert "bad-cmd" in error_msg
|
||||
assert "allowed_commands=None" in error_msg
|
||||
|
||||
def test_args_and_env_still_work(self):
|
||||
"""Existing args and env functionality should be unaffected."""
|
||||
transport = StdioTransport(
|
||||
command="python",
|
||||
args=["server.py", "--port", "8080"],
|
||||
env={"API_KEY": "test123"},
|
||||
)
|
||||
assert transport.command == "python"
|
||||
assert transport.args == ["server.py", "--port", "8080"]
|
||||
assert transport.env == {"API_KEY": "test123"}
|
||||
Reference in New Issue
Block a user