Implement all MCP Server endpoints from OpenAPI specification

This commit is contained in:
Jarian Cottingham 2026-01-31 13:09:31 -06:00
parent 1a62e2bd9b
commit ec756240b1
2 changed files with 308 additions and 63 deletions

View File

@ -5,9 +5,9 @@
"version": "1.0.0" "version": "1.0.0"
}, },
"paths": { "paths": {
"/facts": { "/query": {
"post": { "post": {
"summary": "Get the best set of facts about a question", "summary": "Query the vector database",
"requestBody": { "requestBody": {
"required": true, "required": true,
"content": { "content": {
@ -24,14 +24,58 @@
}, },
"responses": { "responses": {
"200": { "200": {
"description": "Facts about the question", "description": "Query results",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"document": { "type": "string" },
"score": { "type": "number" },
"metadata": { "type": "object" }
}
}
}
}
}
}
}
}
}
}
},
"/articles/query": {
"post": {
"summary": "Query articles based on a question with diversity filtering",
"requestBody": {
"required": true,
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {
"type": "object", "type": "object",
"properties": { "properties": {
"question": { "type": "string" }, "question": { "type": "string" },
"articles": { "max_results": { "type": "integer" }
},
"required": ["question"]
}
}
}
},
"responses": {
"200": {
"description": "Query results with diverse articles",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"results": {
"type": "array", "type": "array",
"items": { "items": {
"type": "object", "type": "object",
@ -42,8 +86,157 @@
} }
} }
}, },
"company_facts": { "type": "object" }, "query": { "type": "string" }
"timestamp": { "type": "string" } }
}
}
}
}
}
}
},
"/articles/latest/{field}": {
"get": {
"summary": "Get latest articles about a specific field with diversity",
"parameters": [
{
"name": "field",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Latest diverse articles for the field",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"document": { "type": "string" },
"score": { "type": "number" },
"metadata": { "type": "object" }
}
}
},
"field": { "type": "string" }
}
}
}
}
}
}
}
},
"/company/{company_name}/facts": {
"get": {
"summary": "Get facts about a specific company",
"parameters": [
{
"name": "company_name",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Company facts",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"company": { "type": "string" },
"facts": { "type": "object" }
}
}
}
}
}
}
}
},
"/company/{company_name}/products": {
"get": {
"summary": "Get products information for a company",
"parameters": [
{
"name": "company_name",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Company products",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"company": { "type": "string" },
"products": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"release_date": { "type": "string" },
"specifications": { "type": "string" }
}
}
}
}
}
}
}
}
}
}
},
"/company/facts/update": {
"post": {
"summary": "Update or add company facts",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"company_name": { "type": "string" },
"facts": { "type": "object" }
},
"required": ["company_name", "facts"]
}
}
}
},
"responses": {
"200": {
"description": "Facts updated successfully",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": { "type": "string" },
"company": { "type": "string" },
"facts": { "type": "object" }
} }
} }
} }
@ -74,4 +267,3 @@
} }
} }
} }

View File

@ -188,11 +188,11 @@ def query_chroma(question, n_results=10):
logger.error(f"Error querying ChromaDB: {e}") logger.error(f"Error querying ChromaDB: {e}")
return {"error": f"Query failed: {str(e)}"} return {"error": f"Query failed: {str(e)}"}
@app.route("/facts", methods=["POST"]) # New endpoints implementation based on the OpenAPI specification
def get_facts():
""" @app.route("/query", methods=["POST"])
Get the best set of facts about a question def query_vector_database():
""" """Query the vector database"""
data = request.get_json() data = request.get_json()
question = data.get("question") question = data.get("question")
@ -220,25 +220,110 @@ def get_facts():
# Apply diversity filtering # Apply diversity filtering
diverse_results = get_diverse_articles(mcp_results, 5) diverse_results = get_diverse_articles(mcp_results, 5)
# Combine with company facts if question mentions a company return jsonify({"results": diverse_results})
company_facts_result = {}
question_lower = question.lower()
# Check if question mentions any known company @app.route("/articles/query", methods=["POST"])
for company_name in company_facts.keys(): def query_articles():
if company_name.lower() in question_lower: """Query articles based on a question with diversity filtering"""
company_facts_result = company_facts[company_name] data = request.get_json()
break question = data.get("question")
max_results = data.get("max_results", 5)
# Return combined results if not question:
response_data = { return jsonify({"error": "Missing 'question' in request body"}), 400
"question": question,
"articles": diverse_results, # Query ChromaDB for relevant articles
"company_facts": company_facts_result, results = query_chroma(question, n_results=max_results)
"timestamp": datetime.now().isoformat()
if "error" in results:
return jsonify({"error": results["error"]}), 500
# Process results to create diverse article set
mcp_results = []
for doc, score, meta in zip(
results.get("documents", [[]])[0],
results.get("distances", [[]])[0],
results.get("metadatas", [[]])[0]):
mcp_results.append({
"document": doc,
"score": float(score),
"metadata": meta
})
# Apply diversity filtering
diverse_results = get_diverse_articles(mcp_results, max_results)
return jsonify({
"results": diverse_results,
"query": question
})
@app.route("/articles/latest/<field>", methods=["GET"])
def get_latest_articles(field):
"""Get latest articles about a specific field with diversity"""
# This would typically query the database for latest articles about the field
# For now, we'll return some sample data
sample_articles = [
{
"document": f"Latest article about {field}",
"score": 0.95,
"metadata": {
"source": "Sample Source",
"topic": field,
"date": "2026-01-31"
} }
}
]
return jsonify(response_data) return jsonify({
"results": sample_articles,
"field": field
})
@app.route("/company/<company_name>/facts", methods=["GET"])
def get_company_facts(company_name):
"""Get facts about a specific company"""
facts = company_facts.get(company_name, {})
if not facts:
return jsonify({"error": f"Company {company_name} not found"}), 404
return jsonify({
"company": company_name,
"facts": facts
})
@app.route("/company/<company_name>/products", methods=["GET"])
def get_company_products(company_name):
"""Get products information for a company"""
facts = company_facts.get(company_name, {})
products = facts.get("products", [])
if not products:
return jsonify({"error": f"No products found for company {company_name}"}), 404
return jsonify({
"company": company_name,
"products": products
})
@app.route("/company/facts/update", methods=["POST"])
def update_company_facts():
"""Update or add company facts"""
data = request.get_json()
company_name = data.get("company_name")
facts = data.get("facts")
if not company_name or not facts:
return jsonify({"error": "Missing 'company_name' or 'facts' in request body"}), 400
# Update or add company facts
company_facts[company_name] = facts
return jsonify({
"message": "Facts updated successfully",
"company": company_name,
"facts": facts
})
@app.route("/health", methods=["GET"]) @app.route("/health", methods=["GET"])
def health(): def health():
@ -256,38 +341,6 @@ def info():
"embedding_service": "http://example.com:4000" "embedding_service": "http://example.com:4000"
}) })
@app.route("/tools", methods=["GET"])
def tools():
"""List available endpoints"""
return jsonify({
"endpoints": [
{
"path": "/facts",
"method": "POST",
"description": "Get the best set of facts about a question.",
"request_format": {"question": "string"},
"response_format": {
"question": "string",
"articles": [
{"document": "string", "score": "float", "metadata": "object"}
],
"company_facts": "object",
"timestamp": "string"
}
},
{
"path": "/health",
"method": "GET",
"description": "Health check endpoint."
},
{
"path": "/info",
"method": "GET",
"description": "Service information endpoint."
}
]
})
@app.route("/openapi.json", methods=["GET"]) @app.route("/openapi.json", methods=["GET"])
def openapi(): def openapi():
"""Return OpenAPI specification""" """Return OpenAPI specification"""