kensho-kfinance 3.2.2__py3-none-any.whl → 3.2.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kensho_kfinance-3.2.2.dist-info → kensho_kfinance-3.2.4.dist-info}/METADATA +2 -2
- {kensho_kfinance-3.2.2.dist-info → kensho_kfinance-3.2.4.dist-info}/RECORD +15 -14
- kfinance/CHANGELOG.md +6 -0
- kfinance/conftest.py +12 -1
- kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_models.py +7 -1
- kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_tools.py +43 -23
- kfinance/domains/mergers_and_acquisitions/tests/test_merger_and_acquisition_tools.py +28 -14
- kfinance/integrations/local_mcp/kfinance_mcp.py +22 -0
- kfinance/integrations/local_mcp/local_mcp.py +2 -2
- kfinance/integrations/tool_calling/all_tools.py +9 -0
- kfinance/version.py +16 -3
- {kensho_kfinance-3.2.2.dist-info → kensho_kfinance-3.2.4.dist-info}/WHEEL +0 -0
- {kensho_kfinance-3.2.2.dist-info → kensho_kfinance-3.2.4.dist-info}/licenses/AUTHORS.md +0 -0
- {kensho_kfinance-3.2.2.dist-info → kensho_kfinance-3.2.4.dist-info}/licenses/LICENSE +0 -0
- {kensho_kfinance-3.2.2.dist-info → kensho_kfinance-3.2.4.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kensho-kfinance
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.4
|
|
4
4
|
Summary: Python CLI for kFinance
|
|
5
5
|
Author-email: Luke Brown <luke.brown@kensho.com>, Michelle Keoy <michelle.keoy@kensho.com>, Keith Page <keith.page@kensho.com>, Matthew Rosen <matthew.rosen@kensho.com>, Nick Roshdieh <nick.roshdieh@kensho.com>
|
|
6
6
|
Project-URL: source, https://github.com/kensho-technologies/kfinance
|
|
@@ -14,7 +14,7 @@ License-File: LICENSE
|
|
|
14
14
|
License-File: AUTHORS.md
|
|
15
15
|
Requires-Dist: cachetools<6,>=5.5
|
|
16
16
|
Requires-Dist: click<=9,>=8.2.1
|
|
17
|
-
Requires-Dist: fastmcp
|
|
17
|
+
Requires-Dist: fastmcp>=2.11
|
|
18
18
|
Requires-Dist: langchain-core>=0.3.15
|
|
19
19
|
Requires-Dist: langchain-google-genai<3,>=2.1.5
|
|
20
20
|
Requires-Dist: numpy>=1.22.4
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
kensho_kfinance-3.2.
|
|
2
|
-
kensho_kfinance-3.2.
|
|
3
|
-
kfinance/CHANGELOG.md,sha256=
|
|
1
|
+
kensho_kfinance-3.2.4.dist-info/licenses/AUTHORS.md,sha256=0h9ClbI0pu1oKj1M28ROUsaxrbZg-6ukQGl6X4y9noI,68
|
|
2
|
+
kensho_kfinance-3.2.4.dist-info/licenses/LICENSE,sha256=bsY4blvSgq6o0FMQ3RXa2NCgco--nHCCchLXzxr6kms,83
|
|
3
|
+
kfinance/CHANGELOG.md,sha256=X2CjISKbQr2oXL2f3r3X_grVSulqoOKOcaOfISxR_ls,2895
|
|
4
4
|
kfinance/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
5
|
-
kfinance/conftest.py,sha256=
|
|
5
|
+
kfinance/conftest.py,sha256=FIZNQyfFbldyVmzaLfWbnMGh6RiC4MZwOVax6815_Ms,3754
|
|
6
6
|
kfinance/mcp.py,sha256=LTzCIlqsDKRD-0Xcpa_P99-JmJ8duAneO_-GzM43kjw,424
|
|
7
7
|
kfinance/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
kfinance/version.py,sha256=
|
|
8
|
+
kfinance/version.py,sha256=l9_iMqlxiCOGrY70L8JWiTjDNINwByOH0aKGS6QXJ4I,704
|
|
9
9
|
kfinance/client/README.md,sha256=DA5vg4uz1JmJNiqvYywrj46YNhOr584WO8L83Ysx_Mk,372
|
|
10
10
|
kfinance/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
kfinance/client/batch_request_handling.py,sha256=opwJJAU2JtqH-s4vt8wRqhH34MiU4tQP6Ng7K6b3upA,6561
|
|
@@ -66,10 +66,10 @@ kfinance/domains/line_items/line_item_tools.py,sha256=C-E7W1cNSYRtqXp1ULAaXcxMh6
|
|
|
66
66
|
kfinance/domains/line_items/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
67
67
|
kfinance/domains/line_items/tests/test_line_item_tools.py,sha256=kZXbi_2oaR5cxxQk9Qj7pY0bvL7G3ch9-z9mprvxMGo,4106
|
|
68
68
|
kfinance/domains/mergers_and_acquisitions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
69
|
-
kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_models.py,sha256=
|
|
70
|
-
kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_tools.py,sha256=
|
|
69
|
+
kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_models.py,sha256=hJ87rnRj14FpmeEJDmEXLdUv37pBrcpKSWtb19j_vLQ,418
|
|
70
|
+
kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_tools.py,sha256=8cTI5E6nAUbC45xFshIkNrICjujGo99Ane2xW8Y0IEo,9735
|
|
71
71
|
kfinance/domains/mergers_and_acquisitions/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
72
|
-
kfinance/domains/mergers_and_acquisitions/tests/test_merger_and_acquisition_tools.py,sha256=
|
|
72
|
+
kfinance/domains/mergers_and_acquisitions/tests/test_merger_and_acquisition_tools.py,sha256=ad4vv3qevHAaLZI0t5qEUPqEKTQm-e800ybA2ID5S_o,6640
|
|
73
73
|
kfinance/domains/prices/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
74
74
|
kfinance/domains/prices/price_models.py,sha256=6K2Yi8PQKJ92rf6ulcOSh9rBVOiPcUQD_WIRjpIRuSo,2156
|
|
75
75
|
kfinance/domains/prices/price_tools.py,sha256=KrcJz3GT8iQElfLp0pArVVcV-jckX_Ggj4lgO0s3wkE,7192
|
|
@@ -89,12 +89,13 @@ kfinance/domains/statements/tests/test_statement_tools.py,sha256=E-wIgnCF1946odD
|
|
|
89
89
|
kfinance/integrations/README.md,sha256=GalSN11UHzbLfcNzKAlObNbw5XqMKVXSVzzGlryM3zc,320
|
|
90
90
|
kfinance/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
91
91
|
kfinance/integrations/local_mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
92
|
-
kfinance/integrations/local_mcp/
|
|
92
|
+
kfinance/integrations/local_mcp/kfinance_mcp.py,sha256=UxnRq5f7PF-dVZrUyH2TpBxVdKb7RbLP64AuD1kcy-E,1099
|
|
93
|
+
kfinance/integrations/local_mcp/local_mcp.py,sha256=x2pCV7kFaEJZCHTlbudrByYb8RQX2gjGTD5UPzvhdmA,3778
|
|
93
94
|
kfinance/integrations/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
94
95
|
kfinance/integrations/tests/test_example_notebook.py,sha256=NrqYFn_XyOn0YlV9QYEnNMBB7LEkg70pP1eqiLGxcBE,6529
|
|
95
96
|
kfinance/integrations/tool_calling/README.md,sha256=TSk-AJddoEctzc0HXQvGNac2CckbnWxHcRDtEifSe1w,2029
|
|
96
97
|
kfinance/integrations/tool_calling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
97
|
-
kfinance/integrations/tool_calling/all_tools.py,sha256=
|
|
98
|
+
kfinance/integrations/tool_calling/all_tools.py,sha256=UsmCupFumXx2J5AZU9M0fbihbZhlirzVrOQehpcgbfo,2724
|
|
98
99
|
kfinance/integrations/tool_calling/prompts.py,sha256=4qeW_VLLcxutUFuXnMKa0QD-_jq9qufo03BY-Slz-XU,1718
|
|
99
100
|
kfinance/integrations/tool_calling/tool_calling_models.py,sha256=o1LGGwx8ikwEiZaHEALS4rvymF9O1Mp5dO9LcfFheUI,5856
|
|
100
101
|
kfinance/integrations/tool_calling/static_tools/README.md,sha256=lWQWdLY1tkGxqE8o4f61gc-RCX0doaCnZM0GmcNO6Jo,97
|
|
@@ -107,7 +108,7 @@ kfinance/integrations/tool_calling/static_tools/tests/test_get_n_quarters_ago.py
|
|
|
107
108
|
kfinance/integrations/tool_calling/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
108
109
|
kfinance/integrations/tool_calling/tests/test_tool_calling_models.py,sha256=Ts1pvaYjq9BTR71dMZ73X__bQ7gQynPkQjy-9x2CuyQ,2605
|
|
109
110
|
kfinance/models/permission_models.py,sha256=G0so8ZOsD1YDsCM4he0z5R9M_shUbSRwD3hUDJdqZl0,635
|
|
110
|
-
kensho_kfinance-3.2.
|
|
111
|
-
kensho_kfinance-3.2.
|
|
112
|
-
kensho_kfinance-3.2.
|
|
113
|
-
kensho_kfinance-3.2.
|
|
111
|
+
kensho_kfinance-3.2.4.dist-info/METADATA,sha256=rc_-W3DvkZ-X_MtcKpQUD3I5rcf4pPVZa9BIaBvjyUE,6197
|
|
112
|
+
kensho_kfinance-3.2.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
113
|
+
kensho_kfinance-3.2.4.dist-info/top_level.txt,sha256=kT_kNwVhfQoOAecY8W7uYah5xaHMoHoAdBIvXh6DaKM,9
|
|
114
|
+
kensho_kfinance-3.2.4.dist-info/RECORD,,
|
kfinance/CHANGELOG.md
CHANGED
kfinance/conftest.py
CHANGED
|
@@ -52,7 +52,18 @@ def mock_client(requests_mock: Mocker) -> Client:
|
|
|
52
52
|
additional_matcher=lambda req: req.json().get("identifiers") == ["SPGI"],
|
|
53
53
|
json={"data": {"SPGI": spgi_id_triple}},
|
|
54
54
|
)
|
|
55
|
-
|
|
55
|
+
# Fetch a non-existent company (which will include an error)
|
|
56
|
+
requests_mock.post(
|
|
57
|
+
url="https://kfinance.kensho.com/api/v1/ids",
|
|
58
|
+
additional_matcher=lambda req: req.json().get("identifiers") == ["non-existent"],
|
|
59
|
+
json={
|
|
60
|
+
"data": {
|
|
61
|
+
"non-existent": {
|
|
62
|
+
"error": "No identification triple found for the provided identifier: NON-EXISTENT of type: ticker"
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
)
|
|
56
67
|
# Fetch SPGI and a non-existent company (which will include an error)
|
|
57
68
|
requests_mock.post(
|
|
58
69
|
url="https://kfinance.kensho.com/api/v1/ids",
|
|
@@ -6,10 +6,16 @@ from pydantic import BaseModel
|
|
|
6
6
|
class MergerSummary(BaseModel):
|
|
7
7
|
transaction_id: int
|
|
8
8
|
merger_title: str
|
|
9
|
-
closed_date: date
|
|
9
|
+
closed_date: date | None
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class MergersResp(BaseModel):
|
|
13
13
|
target: list[MergerSummary]
|
|
14
14
|
buyer: list[MergerSummary]
|
|
15
15
|
seller: list[MergerSummary]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AdvisorResp(BaseModel):
|
|
19
|
+
advisor_company_id: str
|
|
20
|
+
advisor_company_name: str
|
|
21
|
+
advisor_type_name: str | None
|
|
@@ -7,7 +7,10 @@ from kfinance.client.batch_request_handling import Task, process_tasks_in_thread
|
|
|
7
7
|
from kfinance.client.kfinance import Company, MergerOrAcquisition, ParticipantInMerger
|
|
8
8
|
from kfinance.client.permission_models import Permission
|
|
9
9
|
from kfinance.domains.companies.company_models import prefix_company_id
|
|
10
|
-
from kfinance.domains.mergers_and_acquisitions.merger_and_acquisition_models import
|
|
10
|
+
from kfinance.domains.mergers_and_acquisitions.merger_and_acquisition_models import (
|
|
11
|
+
AdvisorResp,
|
|
12
|
+
MergersResp,
|
|
13
|
+
)
|
|
11
14
|
from kfinance.integrations.tool_calling.tool_calling_models import (
|
|
12
15
|
KfinanceTool,
|
|
13
16
|
ToolArgsWithIdentifier,
|
|
@@ -23,9 +26,7 @@ class GetMergersFromIdentifiersResp(ToolRespWithErrors):
|
|
|
23
26
|
class GetMergersFromIdentifiers(KfinanceTool):
|
|
24
27
|
name: str = "get_mergers_from_identifiers"
|
|
25
28
|
description: str = dedent("""
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
For example, "Which companies did Microsoft purchase?" or "Which company bought Ben & Jerrys?"
|
|
29
|
+
"Retrieves all merger and acquisition transactions involving the specified company identifier for each specified company identifier. The results are categorized by the company's role in each transaction: target, buyer, or seller. Provides the transaction_id, merger_title, and transaction closed_date (finalization) . Use this tool to answer questions like 'Which companies did Microsoft purchase?', 'Which company acquired Ben & Jerry's?', and 'Who did Pfizer acquire?'"
|
|
29
30
|
""").strip()
|
|
30
31
|
args_schema: Type[BaseModel] = ToolArgsWithIdentifiers
|
|
31
32
|
accepted_permissions: set[Permission] | None = {Permission.MergersPermission}
|
|
@@ -91,9 +92,7 @@ class GetMergerInfoFromTransactionIdArgs(BaseModel):
|
|
|
91
92
|
class GetMergerInfoFromTransactionId(KfinanceTool):
|
|
92
93
|
name: str = "get_merger_info_from_transaction_id"
|
|
93
94
|
description: str = dedent("""
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
For example, "How much was Ben & Jerrys purchased for?" or "What was the price per share for LinkedIn?" or "When did S&P purchase Kensho?"
|
|
95
|
+
"Provides comprehensive information about a specific merger or acquisition transaction, including its timeline (announced date, closed date), participants' company_name and company_id (target, buyers, sellers), and financial consideration details (including monetary values). Use this tool to answer questions like 'When was the acquisition Ben & Jerry's announced?', 'What was the transaction size of Vodafone's acquisition of Mannesmann?', 'How much did S&P purchase Kensho for?'. Always call this for announcement related questions"
|
|
97
96
|
""").strip()
|
|
98
97
|
args_schema: Type[BaseModel] = GetMergerInfoFromTransactionIdArgs
|
|
99
98
|
accepted_permissions: set[Permission] | None = {Permission.MergersPermission}
|
|
@@ -162,32 +161,53 @@ class GetAdvisorsForCompanyInTransactionFromIdentifierArgs(ToolArgsWithIdentifie
|
|
|
162
161
|
transaction_id: int | None = Field(description="The ID of the merger.", default=None)
|
|
163
162
|
|
|
164
163
|
|
|
164
|
+
class GetAdvisorsForCompanyInTransactionFromIdentifierResp(ToolRespWithErrors):
|
|
165
|
+
results: list[AdvisorResp]
|
|
166
|
+
|
|
167
|
+
|
|
165
168
|
class GetAdvisorsForCompanyInTransactionFromIdentifier(KfinanceTool):
|
|
166
169
|
name: str = "get_advisors_for_company_in_transaction_from_identifier"
|
|
167
|
-
description: str =
|
|
170
|
+
description: str = dedent("""
|
|
171
|
+
"Returns a list of advisor companies that provided advisory services to the specified company during a particular merger or acquisition transaction. Use this tool to answer questions like 'Who advised S&P Global during their purchase of Kensho?', 'Which firms advised Ben & Jerry's in their acquisition?'."
|
|
172
|
+
""").strip()
|
|
168
173
|
args_schema: Type[BaseModel] = GetAdvisorsForCompanyInTransactionFromIdentifierArgs
|
|
169
174
|
accepted_permissions: set[Permission] | None = {Permission.MergersPermission}
|
|
170
175
|
|
|
171
|
-
def _run(self, identifier: str, transaction_id: int) ->
|
|
172
|
-
|
|
176
|
+
def _run(self, identifier: str, transaction_id: int) -> dict:
|
|
177
|
+
api_client = self.kfinance_client.kfinance_api_client
|
|
178
|
+
id_triple_resp = api_client.unified_fetch_id_triples(identifiers=[identifier])
|
|
179
|
+
# If the identifier cannot be resolved, return the associated error.
|
|
180
|
+
if id_triple_resp.errors:
|
|
181
|
+
output_model = GetAdvisorsForCompanyInTransactionFromIdentifierResp(
|
|
182
|
+
results=[], errors=list(id_triple_resp.errors.values())
|
|
183
|
+
)
|
|
184
|
+
return output_model.model_dump(mode="json")
|
|
185
|
+
|
|
186
|
+
id_triple = id_triple_resp.identifiers_to_id_triples[identifier]
|
|
187
|
+
|
|
173
188
|
participant_in_merger = ParticipantInMerger(
|
|
174
|
-
kfinance_api_client=
|
|
189
|
+
kfinance_api_client=api_client,
|
|
175
190
|
transaction_id=transaction_id,
|
|
176
191
|
company=Company(
|
|
177
|
-
kfinance_api_client=
|
|
178
|
-
company_id=
|
|
192
|
+
kfinance_api_client=api_client,
|
|
193
|
+
company_id=id_triple.company_id,
|
|
179
194
|
),
|
|
180
195
|
)
|
|
196
|
+
|
|
181
197
|
advisors = participant_in_merger.advisors
|
|
182
198
|
|
|
199
|
+
advisors_response: list[AdvisorResp] = []
|
|
183
200
|
if advisors:
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
201
|
+
for advisor in advisors:
|
|
202
|
+
advisors_response.append(
|
|
203
|
+
AdvisorResp(
|
|
204
|
+
advisor_company_id=prefix_company_id(advisor.company.company_id),
|
|
205
|
+
advisor_company_name=advisor.company.name,
|
|
206
|
+
advisor_type_name=advisor.advisor_type_name,
|
|
207
|
+
)
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
output_model = GetAdvisorsForCompanyInTransactionFromIdentifierResp(
|
|
211
|
+
results=advisors_response, errors=list(id_triple_resp.errors.values())
|
|
212
|
+
)
|
|
213
|
+
return output_model.model_dump(mode="json")
|
|
@@ -46,28 +46,42 @@ class TestGetCompaniesAdvisingCompanyInTransactionFromIdentifier:
|
|
|
46
46
|
def test_get_companies_advising_company_in_transaction_from_identifier(
|
|
47
47
|
self, requests_mock: Mocker, mock_client: Client
|
|
48
48
|
):
|
|
49
|
-
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"advisor_company_name": "Kensho Technologies, Inc.",
|
|
54
|
-
"advisor_type_name": "Professional Mongo Enjoyer",
|
|
55
|
-
}
|
|
56
|
-
]
|
|
49
|
+
advisor_data = {
|
|
50
|
+
"advisor_company_id": 251994106,
|
|
51
|
+
"advisor_company_name": "Kensho Technologies, Inc.",
|
|
52
|
+
"advisor_type_name": "Professional Mongo Enjoyer",
|
|
57
53
|
}
|
|
58
|
-
|
|
59
|
-
expected_response
|
|
60
|
-
|
|
54
|
+
api_response = {"advisors": [deepcopy(advisor_data)]}
|
|
55
|
+
expected_response = {"results": [deepcopy(advisor_data)]}
|
|
56
|
+
expected_response["results"][0]["advisor_company_id"] = f"{COMPANY_ID_PREFIX}251994106"
|
|
57
|
+
transaction_id = 554979212
|
|
61
58
|
requests_mock.get(
|
|
62
|
-
url=f"https://kfinance.kensho.com/api/v1/merger/info/{transaction_id}/advisors/
|
|
59
|
+
url=f"https://kfinance.kensho.com/api/v1/merger/info/{transaction_id}/advisors/{SPGI_COMPANY_ID}",
|
|
63
60
|
json=api_response,
|
|
64
61
|
)
|
|
65
62
|
tool = GetAdvisorsForCompanyInTransactionFromIdentifier(kfinance_client=mock_client)
|
|
66
63
|
args = GetAdvisorsForCompanyInTransactionFromIdentifierArgs(
|
|
67
|
-
identifier="
|
|
64
|
+
identifier="SPGI", transaction_id=transaction_id
|
|
65
|
+
)
|
|
66
|
+
response = tool.run(args.model_dump(mode="json"))
|
|
67
|
+
assert response == expected_response
|
|
68
|
+
|
|
69
|
+
def test_get_companies_advising_company_in_transaction_from_bad_identifier(
|
|
70
|
+
self, requests_mock: Mocker, mock_client: Client
|
|
71
|
+
):
|
|
72
|
+
expected_response = {
|
|
73
|
+
"results": [],
|
|
74
|
+
"errors": [
|
|
75
|
+
"No identification triple found for the provided identifier: NON-EXISTENT of type: ticker"
|
|
76
|
+
],
|
|
77
|
+
}
|
|
78
|
+
transaction_id = 554979212
|
|
79
|
+
tool = GetAdvisorsForCompanyInTransactionFromIdentifier(kfinance_client=mock_client)
|
|
80
|
+
args = GetAdvisorsForCompanyInTransactionFromIdentifierArgs(
|
|
81
|
+
identifier="non-existent", transaction_id=transaction_id
|
|
68
82
|
)
|
|
69
83
|
response = tool.run(args.model_dump(mode="json"))
|
|
70
|
-
assert response == expected_response
|
|
84
|
+
assert response == expected_response
|
|
71
85
|
|
|
72
86
|
|
|
73
87
|
class TestGetMergerInfoFromTransactionId:
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from fastmcp import FastMCP
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class KfinanceMcp(FastMCP):
|
|
5
|
+
"""FastMCP subclass with some kfinance specific adaptations."""
|
|
6
|
+
|
|
7
|
+
def _setup_handlers(self) -> None:
|
|
8
|
+
"""Skip low level input validation for tool calls.
|
|
9
|
+
|
|
10
|
+
We do validate inputs as part of KfinanceTool.run_without_langchain.
|
|
11
|
+
However, the mcp python sdk recently added its own low-level validation:
|
|
12
|
+
github.com/modelcontextprotocol/python-sdk/commit/c8bbfc034d5cb876d6b91185cf02da2af6fb8b44
|
|
13
|
+
This causes problems because claude always returns integer values as strings if
|
|
14
|
+
they are part of a field that allows multiple types. e.g. `start_year: int | None`
|
|
15
|
+
-> Claude will always return strings. This is fine for pydantic, it automatically
|
|
16
|
+
converts the strings to integers.
|
|
17
|
+
However, the mcp sdk validation is stricter and disallows strings where ints are
|
|
18
|
+
required.
|
|
19
|
+
call_tool(validate_input=False) turns off the mcp sdk validation.
|
|
20
|
+
"""
|
|
21
|
+
super()._setup_handlers()
|
|
22
|
+
self._mcp_server.call_tool(validate_input=False)(self._mcp_call_tool)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from typing import Literal, Optional
|
|
2
2
|
|
|
3
3
|
import click
|
|
4
|
-
from fastmcp import FastMCP
|
|
5
4
|
from fastmcp.tools import FunctionTool
|
|
6
5
|
from fastmcp.utilities.logging import get_logger
|
|
7
6
|
from langchain_core.utils.function_calling import convert_to_openai_tool
|
|
8
7
|
|
|
9
8
|
from kfinance.client.kfinance import Client
|
|
9
|
+
from kfinance.integrations.local_mcp.kfinance_mcp import KfinanceMcp
|
|
10
10
|
from kfinance.integrations.tool_calling.tool_calling_models import KfinanceTool
|
|
11
11
|
|
|
12
12
|
|
|
@@ -76,7 +76,7 @@ def run_mcp(
|
|
|
76
76
|
logger.info("The client will be authenticated using a browser")
|
|
77
77
|
kfinance_client = Client()
|
|
78
78
|
|
|
79
|
-
kfinance_mcp:
|
|
79
|
+
kfinance_mcp: KfinanceMcp = KfinanceMcp("Kfinance")
|
|
80
80
|
for langchain_tool in kfinance_client.langchain_tools:
|
|
81
81
|
logger.info("Adding %s to server", langchain_tool.name)
|
|
82
82
|
kfinance_mcp.add_tool(build_mcp_tool_from_kfinance_tool(langchain_tool))
|
|
@@ -20,6 +20,11 @@ from kfinance.domains.earnings.earning_tools import (
|
|
|
20
20
|
GetTranscriptFromKeyDevId,
|
|
21
21
|
)
|
|
22
22
|
from kfinance.domains.line_items.line_item_tools import GetFinancialLineItemFromIdentifiers
|
|
23
|
+
from kfinance.domains.mergers_and_acquisitions.merger_and_acquisition_tools import (
|
|
24
|
+
GetAdvisorsForCompanyInTransactionFromIdentifier,
|
|
25
|
+
GetMergerInfoFromTransactionId,
|
|
26
|
+
GetMergersFromIdentifiers,
|
|
27
|
+
)
|
|
23
28
|
from kfinance.domains.prices.price_tools import GetPricesFromIdentifiers
|
|
24
29
|
from kfinance.domains.segments.segment_tools import GetSegmentsFromIdentifiers
|
|
25
30
|
from kfinance.domains.statements.statement_tools import GetFinancialStatementFromIdentifiers
|
|
@@ -60,4 +65,8 @@ ALL_TOOLS: list[type[KfinanceTool]] = [
|
|
|
60
65
|
GetSegmentsFromIdentifiers,
|
|
61
66
|
# Statements
|
|
62
67
|
GetFinancialStatementFromIdentifiers,
|
|
68
|
+
# Mergers & Acquisitions
|
|
69
|
+
GetAdvisorsForCompanyInTransactionFromIdentifier,
|
|
70
|
+
GetMergerInfoFromTransactionId,
|
|
71
|
+
GetMergersFromIdentifiers,
|
|
63
72
|
]
|
kfinance/version.py
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# file generated by setuptools-scm
|
|
2
2
|
# don't change, don't track in version control
|
|
3
3
|
|
|
4
|
-
__all__ = [
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
5
12
|
|
|
6
13
|
TYPE_CHECKING = False
|
|
7
14
|
if TYPE_CHECKING:
|
|
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
|
|
|
9
16
|
from typing import Union
|
|
10
17
|
|
|
11
18
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
12
20
|
else:
|
|
13
21
|
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
14
23
|
|
|
15
24
|
version: str
|
|
16
25
|
__version__: str
|
|
17
26
|
__version_tuple__: VERSION_TUPLE
|
|
18
27
|
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
19
30
|
|
|
20
|
-
__version__ = version = '3.2.
|
|
21
|
-
__version_tuple__ = version_tuple = (3, 2,
|
|
31
|
+
__version__ = version = '3.2.4'
|
|
32
|
+
__version_tuple__ = version_tuple = (3, 2, 4)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|