Add members, member detail, RFH suggestions and RFH stats tools
- list_members: search network professionals by sector, country, job title - get_member_detail: full profile with sectors and countries - list_rfh_suggestions: suggestions for a RFH (requester sees all, recipient sees own) - rfh_statistics: aggregated outgoing/incoming RFH metrics + top responding firms - deal_statistics: add country and month group_by options
This commit is contained in:
parent
20e241f925
commit
b598338e3e
150
server.py
150
server.py
|
|
@ -209,8 +209,8 @@ async def list_tools() -> list[types.Tool]:
|
|||
"properties": {
|
||||
"group_by": {
|
||||
"type": "string",
|
||||
"enum": ["stage", "industry", "deal_type", "year", "firm"],
|
||||
"description": "Dimension to group by. Default: 'stage'.",
|
||||
"enum": ["stage", "industry", "deal_type", "year", "month", "firm", "country"],
|
||||
"description": "Dimension to group by. 'month' = per month (YYYY-MM). 'country' = target country. Default: 'stage'.",
|
||||
"default": "stage",
|
||||
},
|
||||
"year_from": {
|
||||
|
|
@ -305,6 +305,123 @@ async def list_tools() -> list[types.Tool]:
|
|||
),
|
||||
inputSchema={"type": "object", "properties": {}, "required": []},
|
||||
),
|
||||
|
||||
types.Tool(
|
||||
name="list_members",
|
||||
description=(
|
||||
"Lists people (professionals) visible to the current user: members of their own firm "
|
||||
"plus members of other firms that have at least one shared deal in the network.\n\n"
|
||||
"Useful for questions like:\n"
|
||||
"- 'Who covers Automotive deals in Germany?'\n"
|
||||
"- 'List all partners in the network'\n"
|
||||
"- 'Who are the directors at [FirmName]?'\n"
|
||||
"- 'Find me someone who covers Healthcare in Italy'\n\n"
|
||||
"Each member includes their firm, job title, city, sectors they cover, and countries."
|
||||
),
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"search": {
|
||||
"type": "string",
|
||||
"description": "Free-text search on name or email.",
|
||||
},
|
||||
"firm_id": {
|
||||
"type": "integer",
|
||||
"description": "Filter by firm ID (use list_firms to get IDs).",
|
||||
},
|
||||
"job_title": {
|
||||
"type": "string",
|
||||
"description": "Partial match on job title. E.g. 'Partner', 'Director', 'Associate'.",
|
||||
},
|
||||
"staff_category": {
|
||||
"type": "string",
|
||||
"description": "Partial match on staff category. E.g. 'partners', 'directors', 'associates'.",
|
||||
},
|
||||
"sector": {
|
||||
"type": "string",
|
||||
"description": "Filter by industry sector covered. E.g. 'Automotive', 'Healthcare', 'Technology'.",
|
||||
},
|
||||
"country": {
|
||||
"type": "string",
|
||||
"description": "Filter by country of activity. E.g. 'Italy', 'Germany', 'France'.",
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"description": "Max results (1–100, default 30).",
|
||||
"default": 30,
|
||||
},
|
||||
"offset": {
|
||||
"type": "integer",
|
||||
"description": "Pagination offset (default 0).",
|
||||
"default": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
|
||||
types.Tool(
|
||||
name="get_member_detail",
|
||||
description=(
|
||||
"Returns the full profile of a single network member by their ID, including "
|
||||
"job title, city, phone numbers, firm, all sectors covered, countries of activity, "
|
||||
"and their professional summary."
|
||||
),
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"member_id": {
|
||||
"type": "integer",
|
||||
"description": "The numeric ID of the member (from list_members).",
|
||||
}
|
||||
},
|
||||
"required": ["member_id"],
|
||||
},
|
||||
),
|
||||
|
||||
types.Tool(
|
||||
name="list_rfh_suggestions",
|
||||
description=(
|
||||
"Returns all suggestions (buy-side leads / candidates) submitted for a specific "
|
||||
"Request for Help (RFH).\n\n"
|
||||
"If the RFH was created by YOUR firm: you see all suggestions from all responding firms.\n"
|
||||
"If it's an incoming RFH: you see only your firm's own submissions.\n\n"
|
||||
"Each suggestion includes: suggesting firm, status (New/Go/No Go/Read), "
|
||||
"whether it was selected, company info, financials (Turnover, EBITDA), and reasoning.\n\n"
|
||||
"Use list_my_requests_for_help or list_incoming_requests to find RFH IDs first."
|
||||
),
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"rfh_id": {
|
||||
"type": "integer",
|
||||
"description": "The ID of the Request for Help (IdRequestForHelp).",
|
||||
}
|
||||
},
|
||||
"required": ["rfh_id"],
|
||||
},
|
||||
),
|
||||
|
||||
types.Tool(
|
||||
name="rfh_statistics",
|
||||
description=(
|
||||
"Returns aggregated statistics on Requests for Help (RFH) activity for the current firm.\n\n"
|
||||
"Covers two dimensions:\n"
|
||||
"1. **Outgoing RFH** (requests my firm sent): how many, open vs closed, "
|
||||
"how many received no response, average suggestions received, "
|
||||
"breakdown by suggestion status (Go/No Go/New/Read), selected suggestions, "
|
||||
"and which firms in the network respond most actively.\n\n"
|
||||
"2. **Incoming RFH** (requests from other firms targeting my firm): "
|
||||
"how many we've been asked, how many we haven't answered yet, "
|
||||
"our response rate, average days to respond, "
|
||||
"and breakdown of our suggestions by status.\n\n"
|
||||
"Example questions:\n"
|
||||
"- 'How are our Requests for Help performing?'\n"
|
||||
"- 'Which firms send us the most suggestions?'\n"
|
||||
"- 'How many incoming RFH have we not answered yet?'\n"
|
||||
"- 'What is our average response time on incoming requests?'"
|
||||
),
|
||||
inputSchema={"type": "object", "properties": {}, "required": []},
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -410,6 +527,35 @@ async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
|
|||
result = await _get("/firms")
|
||||
return await respond(result)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
elif name == "list_members":
|
||||
params: dict[str, Any] = {}
|
||||
for key in ("search", "job_title", "staff_category", "sector", "country"):
|
||||
if arguments.get(key):
|
||||
params[key] = arguments[key]
|
||||
for key in ("firm_id", "limit", "offset"):
|
||||
if arguments.get(key) is not None:
|
||||
params[key] = int(arguments[key])
|
||||
result = await _get("/members", params)
|
||||
return await respond(result)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
elif name == "get_member_detail":
|
||||
member_id = int(arguments["member_id"])
|
||||
result = await _get(f"/member/{member_id}")
|
||||
return await respond(result)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
elif name == "list_rfh_suggestions":
|
||||
rfh_id = int(arguments["rfh_id"])
|
||||
result = await _get(f"/rfh/{rfh_id}/suggestions")
|
||||
return await respond(result)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
elif name == "rfh_statistics":
|
||||
result = await _get("/rfh-stats")
|
||||
return await respond(result)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
else:
|
||||
return [types.TextContent(type="text", text=f"Unknown tool: {name}")]
|
||||
|
|
|
|||
Loading…
Reference in New Issue