1
00:00:00,000 --> 00:00:02,919
Working with databases during development often slows you down.

2
00:00:03,240 --> 00:00:09,220
You're constantly switching between code, your database, trying to understand schemas, setting up test data.

3
00:00:09,580 --> 00:00:10,960
All of this breaks your flow.

4
00:00:11,560 --> 00:00:15,400
AI agents can help, but by default, they cannot reach your database.

5
00:00:15,939 --> 00:00:17,399
That's where MCP comes in.

6
00:00:17,980 --> 00:00:24,000
MCP can act as a bridge, extending your AI agent with the ability to query and interact with your database directly.

7
00:00:24,539 --> 00:00:29,019
In this session, we'll show you how to do this with Postgres using an MCP server.

8
00:00:30,000 --> 00:00:33,600
This way, you can supercharge your developer workflow without compromises.

9
00:00:41,040 --> 00:00:44,600
Hi everyone, welcome to Technology Explorations at Dataminded.

10
00:00:44,799 --> 00:00:48,859
In this series, we aim to give you an initial look at new or interesting technologies.

11
00:00:49,420 --> 00:00:51,939
My name is Jonny, knowledge lead here at Dataminded.

12
00:00:52,039 --> 00:00:56,159
And for today, I've invited Emil to dive into the MCP and Postgres world.

13
00:00:56,380 --> 00:00:57,039
Hi Emil.

14
00:00:58,040 --> 00:00:59,240
Hi, how are you doing?

15
00:00:59,399 --> 00:00:59,920
I'm good here.

16
00:01:00,000 --> 00:01:00,359
How are you?

17
00:01:00,960 --> 00:01:02,079
Yeah, all good as well.

18
00:01:02,179 --> 00:01:05,640
Okay, I propose we will dive right into what you're going to show us.

19
00:01:06,060 --> 00:01:07,640
But maybe a first question.

20
00:01:07,780 --> 00:01:11,760
What made you decide to explore a database connection with an AI agent?

21
00:01:13,840 --> 00:01:16,799
I don't like writing SQL very, very much.

22
00:01:16,900 --> 00:01:21,739
And I find that it takes me quite a long time to write good SQL, even with AI help.

23
00:01:22,480 --> 00:01:27,099
And I thought maybe I could just talk to my database using natural language

24
00:01:27,760 --> 00:01:29,159
and not use SQL.

25
00:01:29,260 --> 00:01:29,920
Or at least not.

26
00:01:30,000 --> 00:01:32,019
But I think I was able to do that in the initial stages of my exploration.

27
00:01:32,280 --> 00:01:38,760
And this led me to MCP servers connecting directly to, in my case, Postgres database.

28
00:01:39,159 --> 00:01:41,280
Okay, so the goal here is avoiding SQL.

29
00:01:42,319 --> 00:01:49,760
Yes, or without hard feelings towards SQL, streamlining your processing by not spending

30
00:01:49,760 --> 00:01:50,980
that much time writing queries.

31
00:01:52,359 --> 00:01:52,840
Yeah.

32
00:01:53,239 --> 00:01:55,939
Okay, I propose we have a look at what it can do.

33
00:01:57,120 --> 00:01:57,599
Absolutely.

34
00:01:57,780 --> 00:01:58,739
Let me share my screen.

35
00:02:01,680 --> 00:02:08,340
So here I'm going to jump right in and write a couple of questions I have about my data

36
00:02:08,340 --> 00:02:08,939
in the prompt.

37
00:02:09,139 --> 00:02:11,340
And we can see the MCP server in action.

38
00:02:12,439 --> 00:02:18,419
So I'm using here an employee database with fake HR data that we can use for illustration

39
00:02:18,419 --> 00:02:19,020
purposes.

40
00:02:20,119 --> 00:02:22,460
So let's start with something simple.

41
00:02:22,560 --> 00:02:24,259
How many employees do we have?

42
00:02:27,279 --> 00:02:28,919
And let's see what it does.

43
00:02:30,000 --> 00:02:36,120
It knows it has to call the tool right away and lists tables, gets some information and

44
00:02:36,599 --> 00:02:40,800
calls a query that you can see by the way yourself in case you'd like to double check

45
00:02:41,419 --> 00:02:41,939
other information.

46
00:02:42,580 --> 00:02:44,060
And this is the correct result.

47
00:02:44,860 --> 00:02:50,900
Let's ask something a little bit more involved if all of them are assigned to a department

48
00:02:50,900 --> 00:02:51,599
at the moment.

49
00:02:51,840 --> 00:02:54,979
So in this case, the AI agent knows what to call.

50
00:02:55,060 --> 00:02:56,020
We'll dive into that later.

51
00:02:56,139 --> 00:02:57,659
It knows which tools are available.

52
00:02:57,780 --> 00:02:59,419
And here I see it executing.

53
00:02:59,599 --> 00:02:59,979
Right.

54
00:03:00,000 --> 00:03:01,939
So it's using real queries to answer your question.

55
00:03:02,120 --> 00:03:02,599
Exactly.

56
00:03:03,240 --> 00:03:03,740
Exactly.

57
00:03:03,800 --> 00:03:08,219
It knows on its own what tool is best fit for a job.

58
00:03:09,520 --> 00:03:11,840
And all of them are assigned to department.

59
00:03:11,939 --> 00:03:15,620
Let's have a third and last question about the data.

60
00:03:16,120 --> 00:03:23,580
If all of them are in a current role or maybe someone is maybe in between roles or not currently

61
00:03:23,580 --> 00:03:24,599
assigned to any role.

62
00:03:24,780 --> 00:03:27,639
And the describe table, could you open that one up while it's thinking?

63
00:03:27,939 --> 00:03:28,639
So it fetches.

64
00:03:28,939 --> 00:03:29,759
So we see always.

65
00:03:30,000 --> 00:03:33,740
So we see the parameters it passes and then the result it gets back.

66
00:03:34,460 --> 00:03:34,979
Right.

67
00:03:35,759 --> 00:03:40,099
And we see that 15% are currently not in an active assignment.

68
00:03:40,939 --> 00:03:42,560
Yeah, it did a good job so far.

69
00:03:42,680 --> 00:03:48,400
But now let's tackle something more that corresponds more to my day to day life.

70
00:03:49,159 --> 00:03:52,280
People come with certain complaints or data inconsistencies.

71
00:03:52,319 --> 00:03:55,180
And my job is to troubleshoot and debug them.

72
00:03:55,360 --> 00:03:59,979
So one of those inconsistencies is just to give you a little bit of the background.

73
00:04:00,000 --> 00:04:07,379
Here we have a table where we see the percentile of your salary on the department basis.

74
00:04:07,759 --> 00:04:11,099
So we've been this department who is at which percentile.

75
00:04:11,120 --> 00:04:18,360
And we had a report from a person who is the head of customer service and earning 80k.

76
00:04:18,519 --> 00:04:24,439
And he's at the 70th percentile in his department, which is a bit strange, him supposedly being

77
00:04:24,439 --> 00:04:25,339
the highest earner.

78
00:04:25,379 --> 00:04:29,899
So let's use MCP to diagnose this and dive into this.

79
00:04:29,939 --> 00:04:29,980
Okay.

89
00:04:32,000 --> 00:04:35,839
So my prompt is I've been hearing that the salary percentile on the department level

90
00:04:36,480 --> 00:04:36,959
aren't correct.

91
00:04:38,800 --> 00:04:39,279
Investigate.

92
00:04:41,240 --> 00:04:41,720
Okay.

93
00:04:41,740 --> 00:04:46,379
So in this case, Cursor's model makes a plan first, and then it goes to the steps.

94
00:04:46,459 --> 00:04:50,899
And in the steps, it will use your MCP agent to call the database.

95
00:04:51,360 --> 00:04:51,839
Correct.

96
00:04:53,719 --> 00:04:56,500
So let's go through what it's doing.

97
00:04:56,600 --> 00:04:59,860
So this is a dbt project.

98
00:04:59,939 --> 00:04:59,980
Right.

99
00:05:00,800 --> 00:05:06,819
So this is a project that uses source tables and builds some other data marts and other

100
00:05:06,819 --> 00:05:08,319
business intelligence tables here.

101
00:05:08,480 --> 00:05:17,120
So here, after getting some table samples from the database, it already jumps into the

102
00:05:17,120 --> 00:05:20,839
dbt code that generated the table.

103
00:05:20,980 --> 00:05:26,300
So here we see the intersection between this being used as a query tool or a fast query

104
00:05:26,300 --> 00:05:26,639
tool.

105
00:05:27,500 --> 00:05:29,800
And actually something that can repair.

107
00:05:30,000 --> 00:05:35,899
What you see in the database, which is, I think the unique, the unique mix of the two.

108
00:05:36,339 --> 00:05:39,779
So so let's see what else.

109
00:05:39,819 --> 00:05:40,339
This is really nice.

110
00:05:40,420 --> 00:05:46,579
So it looks at the code, which is in the repository of this project, which is SQL wrapped in dbt,

111
00:05:46,720 --> 00:05:48,379
of course, or using dbt as a framework.

112
00:05:48,860 --> 00:05:51,579
And it also can look at the data at the same time.

113
00:05:51,800 --> 00:05:56,199
So it can bring those two together to solve your problem in this case.

114
00:05:57,300 --> 00:05:57,740
Exactly.

115
00:05:57,759 --> 00:05:59,980
And here it points me to the database.

117
00:06:00,000 --> 00:06:04,500
So I can see that I have a dbt model where I was missing a partition by department and

118
00:06:04,500 --> 00:06:07,300
to fix it, I need to add this line in my model.

119
00:06:08,180 --> 00:06:12,980
So first it verified using the MCP that the data indeed is not correct in the database.

120
00:06:13,160 --> 00:06:18,480
And then it already see how this data is generated and it fixes this.

121
00:06:18,660 --> 00:06:21,779
So would you like me to create a fix for this issue in a dbt model?

122
00:06:22,000 --> 00:06:22,680
So let's say yes.

123
00:06:22,699 --> 00:06:27,300
So if you say yes, I expect it will do an addition of one line in your model.

124
00:06:29,339 --> 00:06:29,819
Aha.

125
00:06:29,939 --> 00:06:29,980
Okay.

126
00:06:30,000 --> 00:06:31,500
And you're asking to write a unit test.

127
00:06:31,579 --> 00:06:31,920
I see.

128
00:06:33,180 --> 00:06:34,100
Good practice.

129
00:06:34,139 --> 00:06:35,680
You will avoid future issues.

130
00:06:36,199 --> 00:06:36,680
Absolutely.

131
00:06:40,019 --> 00:06:42,279
So we see it added the correct partition.

132
00:06:42,919 --> 00:06:47,680
So the bug was about, it was giving you the global percentile, not per department.

133
00:06:48,000 --> 00:06:50,000
That was the whole bug.

134
00:06:50,079 --> 00:06:51,939
That's why we saw what we saw.

135
00:06:52,500 --> 00:06:53,899
And then we...

136
00:06:54,579 --> 00:06:55,819
We get a new test.

137
00:06:56,079 --> 00:06:59,699
And we add a new test where it takes actual data from seller analytics.

138
00:07:02,300 --> 00:07:04,220
And maybe it's not the best test.

139
00:07:04,339 --> 00:07:06,139
Maybe we could give it a bit more prompts.

140
00:07:07,900 --> 00:07:09,420
But it's a good direction.

141
00:07:10,060 --> 00:07:10,579
Yeah.

142
00:07:10,800 --> 00:07:11,319
Yeah.

143
00:07:11,540 --> 00:07:15,899
I think this is really cool because it shows how your development flow is now.

144
00:07:16,019 --> 00:07:16,860
You have a bug.

145
00:07:17,079 --> 00:07:22,480
You can ask the agent to actually connect your code to the real scenario, the real data

146
00:07:22,480 --> 00:07:23,040
in the database.

147
00:07:23,500 --> 00:07:24,839
It proposes a fix.

148
00:07:24,980 --> 00:07:28,560
And you can ask it to write at least a starting point for a unit test.

149
00:07:30,000 --> 00:07:34,920
And it's like, you need some mental capacity to verify that what it does is actually good.

150
00:07:35,120 --> 00:07:39,980
So you still need to go a bit deeper to make sure that what it actually does is valid.

151
00:07:40,100 --> 00:07:41,560
So you still need your expert knowledge.

152
00:07:42,520 --> 00:07:42,920
Absolutely.

153
00:07:43,079 --> 00:07:47,240
And that was one of the main points I wanted to make is that this is not a substitute for

154
00:07:47,240 --> 00:07:52,300
understanding your data because you need to be the judge whether the solutions are correct.

155
00:07:52,379 --> 00:07:54,279
And especially the unit test.

156
00:07:54,339 --> 00:07:57,560
If you don't understand the data, you will not be able to write good unit tests.

157
00:07:57,680 --> 00:07:59,860
So this is a very, very great tool.

158
00:07:59,939 --> 00:07:59,980
Yeah.

175
00:08:00,000 --> 00:08:04,759
It's very useful to have quick hypothesis about what's happening, both on the output

176
00:08:05,279 --> 00:08:08,240
and on the input side in your SQL and in your tables.

177
00:08:08,600 --> 00:08:11,680
You still need to understand the data and take your time doing this.

178
00:08:11,759 --> 00:08:14,399
But once you do it, you're unstoppable.

179
00:08:14,720 --> 00:08:16,839
You are so much faster using this.

180
00:08:17,019 --> 00:08:17,439
Yeah, indeed.

181
00:08:17,620 --> 00:08:23,720
And so during development, I can imagine this is a big difference or a big time saver if

182
00:08:23,720 --> 00:08:24,699
you can use such a tool.

183
00:08:25,780 --> 00:08:26,220
Yes.

184
00:08:26,240 --> 00:08:28,959
I had situations where I could diagnose a bug.

185
00:08:30,000 --> 00:08:34,919
I could do this in a minute or two versus if I did it manually, I would have a chain

186
00:08:34,919 --> 00:08:35,820
of SQL statements.

187
00:08:35,899 --> 00:08:40,480
I would track in different tabs in my pasting it into Google Docs not to lose it.

188
00:08:40,820 --> 00:08:46,679
And it would be such a long chain of queries that will lead me to this hypothesis already

189
00:08:47,799 --> 00:08:48,240
midway.

190
00:08:48,379 --> 00:08:51,360
You forget what you ran a couple of times before.

191
00:08:51,539 --> 00:08:58,500
So this is very good, especially for very chained queries that are not just one query

192
00:08:58,500 --> 00:08:59,639
or one.

193
00:09:00,000 --> 00:09:00,500
It's a simple bug.

194
00:09:00,639 --> 00:09:07,460
And yes, it really reduces your mental capacity needed to actually arrive somewhere.

195
00:09:07,700 --> 00:09:09,980
Yeah, it also seems like a dangerous tool.

196
00:09:10,039 --> 00:09:16,379
If you don't double check, things can happen that you're out of control of or the tests

197
00:09:16,379 --> 00:09:17,559
might not be the right ones.

198
00:09:18,320 --> 00:09:24,019
So you still need to be ready to review whatever comes out of it.

199
00:09:24,840 --> 00:09:25,360
Yes.

200
00:09:25,379 --> 00:09:29,080
And yeah, this is also running on my local database.

201
00:09:29,620 --> 00:09:29,980
Yeah.

221
00:09:30,000 --> 00:09:32,000
So I can see where I upload the latest snapshot from a database.

222
00:09:32,139 --> 00:09:34,620
We're dealing with very, very small amounts of data.

223
00:09:35,059 --> 00:09:38,179
Of course, as we saw, it just did dbt run.

224
00:09:38,299 --> 00:09:41,039
So we need to make sure where you're connected to and.

225
00:09:41,299 --> 00:09:41,600
Yeah.

226
00:09:41,919 --> 00:09:42,620
Okay, cool.

227
00:09:42,799 --> 00:09:43,559
Now I'm curious.

228
00:09:43,720 --> 00:09:44,980
This is something you set up, right?

229
00:09:45,059 --> 00:09:51,259
That's the MCP server bridging the gap between the model, Claude 4 Sonnet I see here, and

230
00:09:51,259 --> 00:09:53,000
then the Postgres database.

231
00:09:53,840 --> 00:09:54,299
Yes.

232
00:09:54,759 --> 00:09:58,659
So the very starting point where you have the config of the server.

233
00:09:58,899 --> 00:09:59,360
Yeah.

234
00:10:00,000 --> 00:10:00,539
So you have the server itself.

235
00:10:00,899 --> 00:10:05,799
You just go to the cursor settings and here you have MCP integrations.

236
00:10:06,559 --> 00:10:08,639
This is the server we've been using.

237
00:10:08,940 --> 00:10:18,179
And behind this, it's just a JSON file where we have the Python executable and the main

238
00:10:18,179 --> 00:10:19,840
entry point to my server.

239
00:10:20,220 --> 00:10:23,460
And that's all it is to integrate this to cursor.

240
00:10:23,919 --> 00:10:27,559
And then the actual MCP server I also have here.

241
00:10:28,440 --> 00:10:29,200
I created it.

242
00:10:30,000 --> 00:10:30,820
It's a fast MCP framework.

243
00:10:31,959 --> 00:10:34,679
And it's really simple.

244
00:10:35,019 --> 00:10:40,259
It's just actually one file server.py where I have various tools.

245
00:10:40,580 --> 00:10:45,480
And the most important one is the one that queries execute query.

246
00:10:45,720 --> 00:10:49,080
Here it's important to also note about safety.

247
00:10:49,279 --> 00:10:55,340
So we generally don't want it to drop tables or insert records or update records.

248
00:10:55,700 --> 00:10:59,320
So I have this manual safety tool built in that.

249
00:11:00,000 --> 00:11:01,659
Here I'm only allowing for select queries.

250
00:11:02,080 --> 00:11:07,940
And this will stop any attempt to drop and recreate tables or to do anything else.

251
00:11:08,899 --> 00:11:13,940
At the same time, I built it kind of from scratch using the fast MCP framework.

252
00:11:14,220 --> 00:11:15,480
I had a look at the landscape today.

253
00:11:15,879 --> 00:11:19,980
There are many ready solutions where no code is required.

254
00:11:20,639 --> 00:11:25,639
And you can have a Postgres MCP server just as a Docker image where all you need to do

255
00:11:25,639 --> 00:11:28,820
is to pass it the connection string and the mode.

256
00:11:28,899 --> 00:11:29,220
Okay.

257
00:11:30,000 --> 00:11:32,440
So you can have the only mode or the read and write mode.

258
00:11:32,700 --> 00:11:33,940
So it has evolved.

259
00:11:34,620 --> 00:11:39,340
This is probably not necessary anymore unless you want some custom behaviors and then have

260
00:11:39,340 --> 00:11:40,379
more of a control.

261
00:11:40,600 --> 00:11:43,179
If you like more control, maybe this is nicer.

262
00:11:43,860 --> 00:11:48,440
I'm also a bit amazed by the ease that you can integrate this into Cursor.

263
00:11:48,539 --> 00:11:50,039
So you had that settings.

264
00:11:50,460 --> 00:11:53,799
You can also control, I guess, the different tools you expose.

265
00:11:54,080 --> 00:11:56,840
Like your server exposes 16 tools I see.

266
00:11:57,379 --> 00:11:57,899
Yes.

267
00:12:00,100 --> 00:12:01,799
Sometimes it's integrated easily.

268
00:12:01,940 --> 00:12:05,019
Sometimes it doesn't know it should call the MCP server.

269
00:12:05,139 --> 00:12:09,879
When you ask a data question, it's not sure if you want to know about dbt models or if

270
00:12:09,879 --> 00:12:11,139
you want to know about the real data.

271
00:12:11,360 --> 00:12:12,820
So sometimes you need to guide it.

272
00:12:13,000 --> 00:12:15,759
I want you to use the MCP tool for this.

273
00:12:15,899 --> 00:12:22,179
I also have two databases and switching database wasn't there out of the box.

274
00:12:22,440 --> 00:12:25,500
So I just created my own switch database.

275
00:12:25,840 --> 00:12:27,480
And then it intelligently knows.

276
00:12:27,899 --> 00:12:29,259
It can use it to switch the database.

277
00:12:29,600 --> 00:12:29,879
Yeah, neat.

278
00:12:30,279 --> 00:12:34,019
You can add some customized options for your context.

279
00:12:34,519 --> 00:12:39,639
But given this file, anybody could actually just run their local MCP server and do what

280
00:12:39,639 --> 00:12:40,700
you just did, right?

281
00:12:41,080 --> 00:12:41,620
Absolutely.

282
00:12:41,679 --> 00:12:42,720
It's that easy.

283
00:12:42,820 --> 00:12:47,840
Anyone with basic Python skills can do it.

284
00:12:47,919 --> 00:12:53,399
That's why I think the uplift of productivity versus effort spent, it's enormous here.

285
00:12:53,539 --> 00:12:57,620
Everyone should do it who has similar use cases at work.

286
00:12:57,700 --> 00:12:57,879
Yeah.

310
00:12:57,899 --> 00:13:01,779
Besides the knowledge you still need in this case, you still need SQL knowledge.

311
00:13:01,840 --> 00:13:03,360
You still need knowledge about your data.

312
00:13:03,919 --> 00:13:07,960
Are there any other pitfalls that you see in hosting something like this?

313
00:13:08,139 --> 00:13:10,559
This is an easy scenario because this is hosted locally.

314
00:13:10,779 --> 00:13:13,340
It's the Postgres running installed via Homebrew.

315
00:13:14,600 --> 00:13:17,419
So this is a local server.

316
00:13:18,299 --> 00:13:24,980
I'm sure it gets more complex when it's a remote server or maybe you want to port forward

317
00:13:24,980 --> 00:13:26,480
and connect to a remote database.

318
00:13:26,639 --> 00:13:27,879
I'm sure there are some connectivity issues.

319
00:13:27,899 --> 00:13:33,139
There are some connectivity or authentication questions that could make it more difficult.

320
00:13:33,959 --> 00:13:40,460
I think this is for this barebone example, I didn't come across any pitfalls or anything

321
00:13:40,460 --> 00:13:42,759
that I found unintuitive or difficult.

322
00:13:43,139 --> 00:13:47,679
I do feel like this is a very good fit for a development use case because you're working

323
00:13:47,679 --> 00:13:49,940
with development data, dummy data.

324
00:13:50,240 --> 00:13:56,720
You're working locally, the MCP servers running locally, but you are still using a remote

325
00:13:56,720 --> 00:13:57,779
model in this case.

326
00:13:57,899 --> 00:14:03,320
Claude 4 Sonnet, which is used by Cursor in this case, as we see in the bottom, that

327
00:14:03,320 --> 00:14:05,299
will receive your data, right?

328
00:14:05,340 --> 00:14:10,240
It will get the data that is used in your prompt, so it will see everything that's going

329
00:14:10,240 --> 00:14:10,720
on there.

330
00:14:11,399 --> 00:14:15,700
So I would be thinking this should not be used with production data, obviously.

331
00:14:15,820 --> 00:14:18,620
What's your thought on that, on sending data around?

332
00:14:18,919 --> 00:14:25,080
So the data I pull in here, generally it's from test environment or dev environment,

333
00:14:25,220 --> 00:14:27,519
and I work with the latest backup.

334
00:14:27,899 --> 00:14:28,779
But you do have a point.

335
00:14:28,899 --> 00:14:34,100
It is something that your organization should agree on and clarify if it's okay to have

336
00:14:34,100 --> 00:14:35,700
production data being sent for this.

337
00:14:36,179 --> 00:14:42,820
Sometimes some bugs surface only in production or are best reproducible in production, or

338
00:14:42,820 --> 00:14:46,580
your other environments don't use production data as often is the case.

339
00:14:47,039 --> 00:14:53,379
So I would be curious to know how it could still be used in these situations if it's

340
00:14:53,379 --> 00:14:54,100
not reproducible.

341
00:14:54,259 --> 00:14:57,440
But I just wanted to maybe talk about alternatives.

342
00:14:57,460 --> 00:14:57,879
I think that's a good question.

360
00:14:57,899 --> 00:15:02,980
I think there are a lot of options to using it this way, and I think MCP servers, postgres

361
00:15:02,980 --> 00:15:06,879
MCP servers, can be built into other tools as well.

362
00:15:07,019 --> 00:15:11,860
For example, Claude Desktop, where you can talk to data and extract exactly the same

363
00:15:11,860 --> 00:15:18,080
insights we did, but it's disconnected from, in this case, dbt, how data was created.

364
00:15:18,419 --> 00:15:23,100
So I think this is the unique selling point here is the intersection of your code base

365
00:15:23,100 --> 00:15:25,460
and the actual output of your data.

366
00:15:25,919 --> 00:15:27,879
So that is what drove me towards this.

368
00:15:27,899 --> 00:15:36,340
to this. I still think it's a tool for technology experts. I would be very cautious giving this tool

369
00:15:36,340 --> 00:15:42,539
to non-technical people or to managers just because they won't be able to verify if this

370
00:15:42,539 --> 00:15:48,960
data is correct or don't understand underlying tables and relationships. I think it's still

371
00:15:48,960 --> 00:15:55,159
something that should stay and be verified by an actual data expert. And so I think we still have,

372
00:15:55,159 --> 00:15:59,620
we'll have our jobs for a while before this is a decision-making tool.

373
00:15:59,779 --> 00:16:07,360
So you're not getting rid of SQL yet, but writing it yourself will be more limited.

374
00:16:07,899 --> 00:16:13,200
I do write SQL still because sometimes it's just the beginning of an exploration or I don't trust

375
00:16:13,200 --> 00:16:18,120
it. So it's still, but it's much, much less. I was thinking about, we did an experiment

376
00:16:18,120 --> 00:16:24,860
with Snowflake where we have the semantic model capabilities that they have offered in

377
00:16:24,860 --> 00:16:25,139
previews.

378
00:16:25,159 --> 00:16:32,039
And there you add some metadata to your analytical warehouse. You say this column is connected to

379
00:16:32,039 --> 00:16:36,460
that column. That's the kind of relationship. And essentially what you're saying here is

380
00:16:36,460 --> 00:16:42,740
because we add dbt also into the mix, the model has access to these kinds of things

381
00:16:42,740 --> 00:16:49,000
because of dbt. So somehow you supply that semantic model, what is in Snowflake directly

382
00:16:49,000 --> 00:16:53,879
into the model using dbt in this case. And I think it's very powerful because it shows

383
00:16:53,879 --> 00:16:54,480
it.

384
00:16:55,159 --> 00:16:58,299
It didn't do the wrong queries. It did the right queries, it seems.

385
00:16:58,539 --> 00:17:06,180
Yes. And yeah, this is where the strength lies for me. It finds the, it confirms the problem

386
00:17:06,180 --> 00:17:14,339
and it fixes it at the very source. And yeah, there's, it's just the full, full, full flow.

387
00:17:15,220 --> 00:17:20,619
Yeah. And the flow that you showed was mainly a bug fix. Somebody notifies you,

388
00:17:20,700 --> 00:17:24,880
I'm seeing some weird data. You enter it in the LLM and it combines,

389
00:17:25,160 --> 00:17:30,220
it's a code, it combines the data. It gives you a fix and it gives you a test. And how

390
00:17:30,220 --> 00:17:35,680
does this help you in other development tasks, like non-bug related, but adding new models

391
00:17:35,680 --> 00:17:39,619
or something like that. Is that also where you think it could be valuable?

392
00:17:41,019 --> 00:17:46,319
Absolutely. You can also use it, mainly rely on the LLM to, to create models. And

393
00:17:46,319 --> 00:17:53,119
then well, that's what I did for, for this project as well. I, I instructed the model

394
00:17:53,119 --> 00:17:55,140
to create this dbt project on top of the source code that was already

395
00:17:56,160 --> 00:17:59,359
existing in my Postgres that was accessible via the MCP.

396
00:17:59,680 --> 00:18:04,200
And then it queried the database for existing staging tables.

397
00:18:04,339 --> 00:18:05,319
It knew what I had.

398
00:18:05,640 --> 00:18:10,700
And then it built the whole dbt project thinking, how can I enrich this data?

399
00:18:10,819 --> 00:18:14,880
And that's how I came up with analytical data like salary percentiles.

400
00:18:15,160 --> 00:18:20,259
So it can also build things from scratch based on what you have already.

401
00:18:20,420 --> 00:18:22,180
So it goes both ways.

402
00:18:22,359 --> 00:18:23,140
This is interesting.

403
00:18:23,140 --> 00:18:28,140
So you could use it to generate sources in dbt and also generate derived tables,

404
00:18:28,920 --> 00:18:33,539
enrich that information that you have as metadata in dbt with better or correct information.

405
00:18:33,819 --> 00:18:34,980
So it's going to cross validate.

406
00:18:35,559 --> 00:18:36,059
Okay.

407
00:18:37,000 --> 00:18:38,599
This is very interesting.

408
00:18:38,900 --> 00:18:43,000
You also mentioned, Emil, that if you would use Claude Desktop, for example,

409
00:18:43,920 --> 00:18:44,900
it would not be as powerful.

410
00:18:45,079 --> 00:18:46,359
Did you do a test with that?

411
00:18:47,259 --> 00:18:48,000
Yes, I did.

412
00:18:48,160 --> 00:18:49,720
And we're here.

413
00:18:49,839 --> 00:18:52,980
We have Claude Desktop and I have this MCP server connected here.

414
00:18:53,140 --> 00:18:55,640
And we can ask the same kind of questions.

415
00:18:55,859 --> 00:19:04,640
So trying to use Claude Desktop and present it with the same issue as we did with Cursor, it still runs the queries.

416
00:19:05,299 --> 00:19:10,000
But all it does, it confirms that the problem exists.

417
00:19:11,000 --> 00:19:12,460
So it says, yes, you're right.

418
00:19:12,559 --> 00:19:14,140
These statistics are not correct.

419
00:19:14,299 --> 00:19:20,640
But there is nothing that actually points me to the right problem.

420
00:19:21,759 --> 00:19:23,119
Because it doesn't work.

421
00:19:23,140 --> 00:19:23,799
It doesn't have the code.

422
00:19:23,920 --> 00:19:26,500
It cannot see how the data was created.

423
00:19:26,660 --> 00:19:32,319
So it also cannot provide a good fix or at least a fix that would make sense.

424
00:19:32,519 --> 00:19:33,460
It has to guess.

425
00:19:34,500 --> 00:19:34,980
Yes.

426
00:19:35,099 --> 00:19:48,519
So my starting point now would be to still ask it to write a couple of SQL queries and just go about it the manual way versus I got everything ready out of the box in the previous demo.

427
00:19:48,740 --> 00:19:52,059
So this is a big benefit of actually doing this in Cursor as you did.

428
00:19:52,140 --> 00:19:52,619
Yeah.

429
00:19:53,140 --> 00:19:54,039
Between the code and the data.

430
00:19:54,140 --> 00:19:56,940
That's the thing that's crucial to getting good results.

431
00:19:57,380 --> 00:19:57,940
Yes.

432
00:19:59,279 --> 00:20:00,000
All right.

433
00:20:00,079 --> 00:20:01,299
We can wrap it up.

434
00:20:01,480 --> 00:20:02,000
I can summarize.

435
00:20:03,060 --> 00:20:03,220
All right.

436
00:20:04,039 --> 00:20:12,519
You can speed up your analytical queries and get insights from data very easily using MCP servers with Postgres.

437
00:20:12,640 --> 00:20:21,960
It can accompany you and support you throughout the entire flow from the development and generation of the data and understanding of the data that currently lives.

438
00:20:22,559 --> 00:20:23,119
Yes.

439
00:20:23,140 --> 00:20:29,279
So that's a huge productivity boost for me that was easy to implement in just a couple of hours.

440
00:20:29,380 --> 00:20:32,759
So if you have a similar use case, give it a shot.

441
00:20:34,079 --> 00:20:34,519
Cool.

442
00:20:34,579 --> 00:20:39,039
And my takeaway is it's very accelerating.

443
00:20:39,380 --> 00:20:46,759
You showed me that in a few minutes you can go from a bug to a solution because you mix in the code with the data.

444
00:20:47,240 --> 00:20:50,759
And I'm also I'm going to try out these MCP servers in Cursor.

445
00:20:50,799 --> 00:20:52,420
I didn't know it was that easy to set up.

446
00:20:53,240 --> 00:20:54,859
You triggered me in using that.

447
00:20:54,960 --> 00:20:58,259
The code you wrote is something we will be put in public.

448
00:20:58,420 --> 00:20:59,640
We have a public repository.

449
00:21:00,500 --> 00:21:00,900
Yes.

450
00:21:01,559 --> 00:21:01,960
Okay.

451
00:21:02,000 --> 00:21:05,079
I'll add the link to the notes as well so everybody can test out your server.

452
00:21:05,259 --> 00:21:05,680
All right.

453
00:21:06,039 --> 00:21:08,000
Thanks a lot, Emil, for this explanation.

454
00:21:08,380 --> 00:21:09,619
I learned quite a few things.

455
00:21:10,099 --> 00:21:11,720
And thanks, everybody, for watching.

456
00:21:11,859 --> 00:21:14,579
This was our MCP Postgres integration by Emil.

457
00:21:14,700 --> 00:21:15,960
So I hope to see you next time.

458
00:21:16,059 --> 00:21:16,799
Thanks for watching.

459
00:21:17,099 --> 00:21:17,640
Bye-bye.

460
00:21:18,739 --> 00:21:19,539
Bye-bye.

461
00:21:19,539 --> 00:21:22,480
Bye-bye.